项目开发中经常会遇到多叉树的展示,最为常见的便是组织机构图以及省市县结构图,
通常做法是接收服务器端返回来的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 }
以上,实现了无线级树节点的构造