Skip to content

Instantly share code, notes, and snippets.

@pfmiles
Last active September 1, 2022 06:47
Show Gist options
  • Save pfmiles/5a6cb9c484660c7241913f4d71968c13 to your computer and use it in GitHub Desktop.
Save pfmiles/5a6cb9c484660c7241913f4d71968c13 to your computer and use it in GitHub Desktop.
树状日志拼装工具, 用于日志跟踪记录递归结构
public class Test {
public static void main(String... args) {
TreeLog log = new TreeLog("test");
log.log("第一层");
TreeLog log1 = log.addChild("test1");
log1.log("第二层");
TreeLog log2 = log1.addChild("test2");
log2.log("第三层");
TreeLog log3 = log.addChild("test3");
log3.log("又一个第二层");
TreeLog log4 = log2.addChild("test4");
log4.log("第四层");
TreeLog log5 = log1.addChild("test5");
log5.log("又一个第三层");
TreeLog log6 = log2.addChild("test6");
log6.log("又一个第四层");
TreeLog log7 = log.addChild("test7");
log7.log("再一个第二层");
System.out.println(log);
}
}
package test;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class TreeLog implements Serializable {
private static final long serialVersionUID = 8786588317154681976L;
private static final String END_CON = "\u2514\u2500";
private static final String CON = "\u251c\u2500";
private static final String IDENT = " ";
private static final String V_IDENT = "\u2502 ";
// 当前层节点标识
private String currentNodeName;
// 当前层节点信息内容
private StringBuilder currentNodeMsg;
// 下层子节点
private List<TreeLog> children;
public TreeLog(String currentNodeName) {
this.currentNodeName = currentNodeName;
}
public void setCurrentNodeName(String currentNodeName) {
this.currentNodeName = currentNodeName;
}
public TreeLog log(Object msg) {
if (this.currentNodeMsg == null)
this.currentNodeMsg = new StringBuilder();
if (msg != null)
this.currentNodeMsg.append(msg);
return this;
}
public TreeLog addChild(String name) {
if (this.children == null)
this.children = new ArrayList<TreeLog>();
TreeLog ret = new TreeLog(name);
this.children.add(ret);
return ret;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
genLog(sb, this, 0, false, new HashSet<Integer>());
return sb.toString();
}
private void genLog(StringBuilder sb, TreeLog cur, int level, boolean hasNextSibling,
Set<Integer> vertIdentIdxes) {
// 生成本层内容的行
if (level == 1) {
sb.append(IDENT);
} else if (level > 1) {
for (int i = 0; i < level * 2 - 1; i++)
if (vertIdentIdxes.contains(i)) {
sb.append(V_IDENT);
} else {
sb.append(IDENT);
}
}
if (level != 0)
if (hasNextSibling)
sb.append(CON);
else
sb.append(END_CON);
sb.append(cur.currentNodeName);
if (cur.currentNodeMsg != null)
sb.append(": ").append(cur.currentNodeMsg);
sb.append('\n');
Set<Integer> childrenVerts = new HashSet<Integer>(vertIdentIdxes);
// 若当前节点后面还有平级节点,则需要通知当前节点的子节点生成竖线的位置
if (hasNextSibling)
childrenVerts.add(level * 2 - 1);
// 生成所有children内容,每个child占用一行, 依顺序排在后面
if (cur.children != null && !cur.children.isEmpty()) {
for (int i = 0; i < cur.children.size(); i++) {
TreeLog c = cur.children.get(i);
genLog(sb, c, level + 1, i != cur.children.size() - 1, childrenVerts);
}
}
}
}
test: 第一层
  ├─test1: 第二层
  │   ├─test2: 第三层
  │   │   ├─test4: 第四层
  │   │   └─test6: 又一个第四层
  │   └─test5: 又一个第三层
  ├─test3: 又一个第二层
  └─test7: 再一个第二层
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment