TreeUtils生成树形结构

TreeUtils生成树形结构

TreeNode

用来表示每个树节点的抽象,即需要生成树的对象需要实现此接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* 树节点父类,所有需要使用{@linkplain TreeUtils}工具类形成树形结构等操作的节点都需要实现该接口
*
* @param <T> 节点id类型
*/
public interface TreeNode<T> {
/**
* 获取节点id
*
* @return 树节点id
*/
T id();

/**
* 获取该节点的父节点id
*
* @return 父节点id
*/
T parentId();

/**
* 是否是根节点
*
* @return true:根节点
*/
boolean root();

/**
* 设置节点的子节点列表
*
* @param children 子节点
*/
void setChildren(List<? extends TreeNode<T>> children);

/**
* 获取所有子节点
*
* @return 子节点列表
*/
List<? extends TreeNode<T>> getChildren();
}

TreeUtils

用来生成树形结构,以及获取所有叶子节点等操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
public class TreeUtils {

/**
* 根据所有树节点列表,生成含有所有树形结构的列表
*
* @param nodes 树形节点列表
* @param <T> 节点类型
* @return 树形结构列表
*/
public static <T extends TreeNode<?>> List<T> generateTrees(List<T> nodes) {
List<T> roots = new ArrayList<>();
for (Iterator<T> ite = nodes.iterator(); ite.hasNext(); ) {
T node = ite.next();
if (node.root()) {
roots.add(node);
// 从所有节点列表中删除该节点,以免后续重复遍历该节点
ite.remove();
}
}

roots.forEach(r -> {
setChildren(r, nodes);
});
return roots;
}

/**
* 从所有节点列表中查找并设置parent的所有子节点
*
* @param parent 父节点
* @param nodes 所有树节点列表
*/
@SuppressWarnings("all")
public static <T extends TreeNode> void setChildren(T parent, List<T> nodes) {
List<T> children = new ArrayList<>();
Object parentId = parent.id();
for (Iterator<T> ite = nodes.iterator(); ite.hasNext(); ) {
T node = ite.next();
if (Objects.equals(node.parentId(), parentId)) {
children.add(node);
// 从所有节点列表中删除该节点,以免后续重复遍历该节点
ite.remove();
}
}
// 如果孩子为空,则直接返回,否则继续递归设置孩子的孩子
if (children.isEmpty()) {
return;
}
parent.setChildren(children);
children.forEach(m -> {
// 递归设置子节点
setChildren(m, nodes);
});
}

/**
* 获取指定树节点下的所有叶子节点
*
* @param parent 父节点
* @param <T> 实际节点类型
* @return 叶子节点
*/
public static <T extends TreeNode<?>> List<T> getLeafs(T parent) {
List<T> leafs = new ArrayList<>();
fillLeaf(parent, leafs);
return leafs;
}

/**
* 将parent的所有叶子节点填充至leafs列表中
*
* @param parent 父节点
* @param leafs 叶子节点列表
* @param <T> 实际节点类型
*/
@SuppressWarnings("all")
public static <T extends TreeNode> void fillLeaf(T parent, List<T> leafs) {
List<T> children = parent.getChildren();
// 如果节点没有子节点则说明为叶子节点
if (CollectionUtils.isEmpty(children)) {
leafs.add(parent);
return;
}
// 递归调用子节点,查找叶子节点
for (T child : children) {
fillLeaf(child, leafs);
}
}
}

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Getter
@Setter
public class ExampleListVO implements TreeNode<Long> {
private Long id;
private Long pid;
private Integer type;
private String name;
private String icon;
private String code;
private Integer status;
private List<ResourceListVO> children;

@Override
public Long id() {
return this.id;
}

@Override
public Long parentId() {
return this.pid;
}

@Override
public boolean root() {
return Objects.equals(this.pid, 0L);
}

@Override
public void setChildren(List children) {
this.children = children;
}
}

调用

1
2
3
4
public List<ExampleListVO> getTreeList() {
List<ExampleListVO> vos = this.exampleMapper.selectList();
return TreeUtils.generateTrees(vos);
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!