在实际项目中,经常会遇到需要封装多级树形结构对象的场景,现将主要过程记录一下。

总体思路

  • 首先获取所有的根节点(顶级节点),即查询parentId = 0的节点。
  • 通过getChildren()方法,封装每个根节点的子节点
    • 递归调用getChildren()方法,逐层封装子节点
    • 若有排序字段,则根据实际场景进行排序
  • 返回结果

Java实体类

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
/**
* 节点对象
*/
@Data
public class Nodes {
/**
* 节点id
*/
private Long id;
/**
* 标题
*/
private String title;
/**
* 父节点id
*/
private Long parentId;
/**
* 排序
*/
private Integer sort;
/**
* 子节点
*/
@ApiModelProperty(value = "子节点")
private List<Nodes> children;
}

封装函数

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
/**
* 获取节点列表(以树形结构返回)
*
* @return 结果
*/
@Override
public List<Nodes> getNestedTreeList() {
// 查出所有节点
List<Nodes> allList = baseDao.selectList(null);
// 封装一级节点
return allList.stream().filter(node -> node.getParentId() == 0).map(node -> {
node.setChildren(getChildren(node, allList));
return node;
}).sorted((node1, node2) -> {
// 排序
return (node1.getSort() == null ? 0 : node1.getSort()) - (node2.getSort() == null ? 0 : node2.getSort());
}).collect(Collectors.toList());
}

/**
* 查询子节点
*
* @param root 父节点
* @param allList 数据集
* @return 结果
*/
private List<Nodes> getChildren(Nodes root, List<Nodes> allList) {
return allList.stream().filter(node -> node.getParentId().equals(root.getId())).map(node -> {
// 递归调用getChildren()方法,封装子节点
node.setChildren(getChildren(node, allList));
return node;
}).sorted((node1, node2) -> {
// 排序
return (node1.getSort() == null ? 0 : node1.getSort()) - (node2.getSort() == null ? 0 : node2.getSort());
}).collect(Collectors.toList());
}