Java实现n级树对象的封装

项目开发中经常会遇到多叉树的展示,最为常见的便是组织机构图以及省市县结构图,
通常做法是接收服务器端返回来的JSON格式的数据,动态生成树形菜单节点。
动态生成树有两种思路:


异步加载节点,适用于节点数量很多的结构,通过zTree等插件封装的方法,传入指定的节点ID查询出当前节点下的子节点信息。
一次性生成全部树节点,适用于小数据量的结构。


今天的笔记记录的是第二种思路的实现方式,共两种

第一种为最常规的做法,将节点以节点编号为Key存入散列表,随后遍历散列表通过Key值与节点的parentId对应关系再构造出多叉树:
————————————————
版权声明:本文为CSDN博主「好像一条狗啊」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yh_Anonymous/article/details/80367695

 1 public class InfiniteLevelTreeUtil {
 2     public static List<Node> getInfiniteLevelTree() {
 3         // 读取层次数据结果集列表
 4         List<Node> dataList = dao.getNodes();
 5         // 将Node存入散列表
 6         Map<String, Node> nodeMap = dataList.stream().collect(Collectors.toMap(Node::getId, node -> node));
 7         // 根节点
 8         List<Node> root = new ArrayList<>();
 9         // 构造无序的多叉树
10         for(Map.Entry<String, Node> entry: nodeMap.entrySet()) {
11             Node node = entry.getValue();
12             if (node.getParentId().equals("-1")) {
13                 root.add(node);
14             } else {
15                 nodeMap.get(node.getParentId()).addChild(node);
16             }
17         }
18         return root;
19     }
20 }
21 // 节点Bean
22 public class Node {
23     private String id;
24     private String name;
25     private String parentId;
26     private int order;
27     private Children children = new Children();
28     // ...get set 方法,构造方法
29 
30     // 兄弟节点排序
31     public void sortChildren() {
32         if (children != null && children.getSize() != 0) {
33             children.sortChildren();
34         }
35     }
36     // 添加孩子节点
37     public void addChild(Node node) {
38         this.children.addChild(node);
39     }
40 }
41 // 子节点Bean
42 public class Children {
43     private List<Node> list = new ArrayList<>();
44     // ...get set 方法,构造方法
45     public int getSize() {
46         return list.size();
47     }
48     public void addChild(Node node) {
49         list.add(node);
50     }
51     // 孩子节点排序
52     public void sortChildren() {
53         Collections.sort(list, new NodeOrderComparator());
54         for (Iterator<Node> it = list.iterator(); it.hasNext();) {
55             it.next().sortChildren();
56         }
57     }
58 }
59 // 节点排序Comparator
60 public class NodeOrderComparator implements Comparator<Node>{
61     // 按照节点排序值进行排序
62     public int compare(Node n1, Node n2) {
63         return (n1.getOrder() < n2.getOrder() ? -1 : (n1.getOrder() == n2.getOrder() ? 0 : 1));
64     }
65 }

第二种做法使用了递归,以parentId = '-1'(根节点)作为递归方法的入口,构造多叉树。

 1 public class InfiniteLevelTreeUtil {
 2     // 入口方法
 3     public List<Node> getInfiniteLevelTree(List<Node> nodeList) {
 4         List<Node> list = new ArrayList<>();
 5         // 遍历节点列表
 6         for (Node node : nodeList) {
 7             if (node.getParentId().equals("-1")) {
 8                 // parentID为-1(根节点)作为入口
 9                 node.setChildren(getChildrenNode(node.getId(), nodeList));
10                 list.add(node);
11             }
12         }
13         // 排序
14         list.sort(new NodeOrderComparator());
15         return list;
16     }
17 
18     // 获取子节点的递归方法
19     public List<Node> getChildrenNode(String id, List<Node> nodeList) {
20         List<Node> lists = new ArrayList<>();
21         for (Node node : nodeList) {
22             if (node.getParentId().equals(id)) {
23                 // 递归获取子节点
24                 node.setChildren(getChildrenNode(node.getId(), nodeList));
25                 lists.add(node);
26             }
27         }
28         // 排序
29         lists.sort(new NodeOrderComparator());
30         return lists;
31     }
32 }
33 
34 // 节点Bean
35 public class Node {
36     private String id;
37     private String name;
38     private String parentId;
39     private int order;
40     private List<Node> children = new ArrayList<>();
41     // ...get set 方法,构造方法
42 }
43 
44 // 节点排序Comparator
45 public class NodeOrderComparator implements Comparator<Node>{
46     // 按照节点排序值进行排序
47     public int compare(Node n1, Node n2) {
48         return (n1.getOrder() < n2.getOrder() ? -1 : (n1.getOrder() == n2.getOrder() ? 0 : 1));
49     }
50 }

测试:

节点列表如下(id,name,pid,order):

1 Node n1 = new Node("0", "根节点", "-1", 0);
2 Node n2 = new Node("01", "一级子节点", "0", 0);
3 Node n3 = new Node("011", "二级子节点1", "01", 3);
4 Node n4 = new Node("012", "二级子节点2", "01", 2);
5 Node n5 = new Node("013", "二级子节点3", "01", 1);
6 Node n6 = new Node("0131", "三级子节点1", "013", 1);
7 Node n7 = new Node("0132", "三级子节点2", "013", 1);

运行方法后得到的树结构的JSON串如下:

 1 {  
 2     'id': '0',   
 3     'name': '根节点',
 4     'children': [{  
 5         'id': '01',   
 6         'name': '一级子节点',
 7         'children': [
 8             {  
 9                 'id': '011',
10                 'name': '二级子节点1',
11                 'children':[]
12             },
13             {  
14                 'id': '012',   
15                 'name': '二级子节点2',
16                 'children': []
17             },
18             {  
19                 'id': '013',   
20                 'name': '二级子节点3',
21                 'children': [
22                     {  
23                         'id': '0131',
24                         'name': '三级子节点1'
25                     },
26                     {  
27                         'id': '01312',
28                         'name': '三级子节点2'
29                     }
30                 ] 
31             }
32         ]  
33     }]  
34 }

以上,实现了无线级树节点的构造

posted @ 2019-09-26 14:57  代码酷  阅读(572)  评论(0编辑  收藏  举报