var data=[
{ id: 40, parentId: 31, note: "的萨达是" },
{ id: 20, parentId: 11, note: "的萨达是" },
{ id: 22, parentId: 20, note: "dsadas" },
{ id: 12, parentId: null, note: "dsadasad萨达s" },
{ id: 11, parentId: undefined, note: "dqwds" },
{ id: 24, parentId: 22, note: "搜索" },
{ id: 34, parentId: 22, note: "搜索" }
]
function fnSetTreeData(data) {
var data = [...data];
var tree = data.filter((father) => {
var branchArr = data.filter((child) => {
if (father.id == child.parentId) child._hasParent = true;
return father.id == child.parentId;
// MARK 为何这样写就报错 ?
// if (father.id == child.parentId) child._hasParent = true;
// return child._hasParent
});
if (branchArr.length > 0) father.children = branchArr;
return !father._hasParent;
});
// MARK 为何在这里还得加一个过滤
tree = tree.filter((item) => {
return !item._hasParent;
})
return tree
}
console.log(JSON.stringify(fnSetTreeData(data), null, 2));
https://segmentfault.com/q/1010000017234194/a-1020000017236512前端
在平时的开发工做中,常常遇到这样一个场景,在数据库中存储了具备父子关系的数据,须要将这些数据以树形结构的形式在界面上进行展现。本文的目的是提供了一个通用的编程模型,解决将具备父子关系的数据转换成树形结构的问题。若有不正之处,欢迎你们批评指正。java
咱们以北京行政区划为例,讲解整个模型。node
北京市:市辖区 县数据库
市辖区:东城区 西城区 朝阳区 丰台区 石景山区 海淀区 门头沟区 房山区 通州区 顺义区 昌平区 大兴区 怀柔区 平谷区编程
县:密云县 延庆县json
TreeNode:定义树的节点对象segmentfault
ITree:定义树对象要实现的方法。后端
Tree:实现 ITree 接口,提供树的完整功能。maven
ITreeNode:定义模板方法,构造树形结构的类要实现该接口,Tree 经过调用该接口中的方法获取 nodeId nodeName parentNodeId orderNum 数据。ide
Org:定义行政区划类,实现 ItreeNode 接口。
TreeNode类:
package com.ips.tree; import java.util.ArrayList; import java.util.List; import com.alibaba.fastjson.annotation.JSONField; /** * <p>Title: 树节点</p> * <p>Description:一棵树由许多包含父子关系的节点组成 </p> * @author liuzhibo * @date 2017年1月18日 */ public class TreeNode { //树节点ID @JSONField(ordinal=1) private String nodeId; //树节点名称 @JSONField(ordinal=2) private String nodeName; //父节点ID @JSONField(ordinal=3) private String parentNodeId; //节点在树中的排序号 @JSONField(ordinal=4) private int orderNum; //节点所在的层级 @JSONField(ordinal=5) private int level; private TreeNode parent; //当前节点的二子节点 @JSONField(ordinal=6) private List<TreeNode> children = new ArrayList<TreeNode>(); //当前节点的子孙节点 private List<TreeNode> allChildren = new ArrayList<TreeNode>(); public TreeNode(ITreeNode obj){ this.nodeId = obj.getNodeId(); this.nodeName = obj.getNodeName(); this.parentNodeId = obj.getNodeParentId(); this.orderNum = obj.getOrderNum(); } public void addChild(TreeNode treeNode){ this.children.add(treeNode); } public void removeChild(TreeNode treeNode){ this.children.remove(treeNode); } public String getNodeId() { return nodeId; } public void setNodeId(String nodeId) { this.nodeId = nodeId; } public String getNodeName() { return nodeName; } public void setNodeName(String nodeName) { this.nodeName = nodeName; } public String getParentNodeId() { return parentNodeId; } public void setParentNodeId(String parentNodeId) { this.parentNodeId = parentNodeId; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public TreeNode getParent() { return parent; } public void setParent(TreeNode parent) { this.parent = parent; } public List<TreeNode> getChildren() { return children; } public void setChildren(List<TreeNode> children) { this.children = children; } public int getOrderNum() { return orderNum; } public void setOrderNum(int orderNum) { this.orderNum = orderNum; } public List<TreeNode> getAllChildren() { if(this.allChildren.isEmpty()){ for(TreeNode treeNode : this.children){ this.allChildren.add(treeNode); this.allChildren.addAll(treeNode.getAllChildren()); } } return this.allChildren; } }
ITree接口:
package com.ips.tree; import java.util.List; public interface ITree { public List<TreeNode> getTree(); public List<TreeNode> getRoot(); public TreeNode getTreeNode(String nodeId); }
Tree类:
package com.ips.tree; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; public class Tree implements ITree { private HashMap<String, TreeNode> treeNodesMap = new HashMap<String, TreeNode>(); private List<TreeNode> treeNodesList = new ArrayList<TreeNode>(); public Tree(List<ITreeNode> list){ initTreeNodeMap(list); initTreeNodeList(); } private void initTreeNodeMap(List<ITreeNode> list){ TreeNode treeNode = null; for(ITreeNode item : list){ treeNode = new TreeNode(item); treeNodesMap.put(treeNode.getNodeId(), treeNode); } Iterator<TreeNode> iter = treeNodesMap.values().iterator(); TreeNode parentTreeNode = null; while(iter.hasNext()){ treeNode = iter.next(); if(treeNode.getParentNodeId() == null || treeNode.getParentNodeId() == ""){ continue; } parentTreeNode = treeNodesMap.get(treeNode.getParentNodeId()); if(parentTreeNode != null){ treeNode.setParent(parentTreeNode); parentTreeNode.addChild(treeNode); } } } private void initTreeNodeList(){ if(treeNodesList.size() > 0){ return; } if(treeNodesMap.size() == 0){ return; } Iterator<TreeNode> iter = treeNodesMap.values().iterator(); TreeNode treeNode = null; while(iter.hasNext()){ treeNode = iter.next(); if(treeNode.getParent() == null){ this.treeNodesList.add(treeNode); this.treeNodesList.addAll(treeNode.getAllChildren()); } } } @Override public List<TreeNode> getTree() { return this.treeNodesList; } @Override public List<TreeNode> getRoot() { List<TreeNode> rootList = new ArrayList<TreeNode>(); if (this.treeNodesList.size() > 0) { for (TreeNode node : treeNodesList) { if (node.getParent() == null) rootList.add(node); } } return rootList; } @Override public TreeNode getTreeNode(String nodeId) { return this.treeNodesMap.get(nodeId); } }
ITreeNode 接口:
package com.ips.tree; public interface ITreeNode { public String getNodeId(); public String getNodeName(); public String getNodeParentId(); public Integer getOrderNum(); }
Org 类:
package com.ips.tree; public class Org implements ITreeNode { private String uuid; private String parentId; private String name; private Integer orderNum; private String code; private String type; public Org(){ } public Org(String uuid, String parentId, String name, Integer orderNum, String code, String type){ this.uuid = uuid; this.parentId = parentId; this.name = name; this.orderNum = orderNum; this.code = code; this.type = type; } @Override public String getNodeId() { return this.uuid; } @Override public String getNodeName() { return this.name; } @Override public String getNodeParentId() { return this.parentId; } @Override public Integer getOrderNum() { return this.orderNum; } public String getUuid() { return uuid; } public void setUuid(String uuid) { this.uuid = uuid; } public String getParentId() { return parentId; } public void setParentId(String parentId) { this.parentId = parentId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getType() { return type; } public void setType(String type) { this.type = type; } public void setOrderNum(Integer orderNum) { this.orderNum = orderNum; } }
TreeDemo 类:执行该类的 main 方法,查看效果。
package com.ips.tree; import java.util.ArrayList; import java.util.List; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SimplePropertyPreFilter; public class TreeDemo { public static void main(String[] args) { Tree tree = new Tree(genOrgList()); TreeNode treeNode = tree.getTreeNode("2"); SimplePropertyPreFilter filter = new SimplePropertyPreFilter(); // 构造方法里,也能够直接传须要序列化的属性名字 filter.getExcludes().add("parent"); filter.getExcludes().add("allChildren"); String data = JSONObject.toJSONString(treeNode, filter); System.out.println(data); } public static List<ITreeNode> genOrgList(){ List<ITreeNode> list = new ArrayList<ITreeNode>(); Org org = new Org("2", "1", "北京市", 2, "110000", "2"); list.add(org); org = new Org("3", "2", "市辖区", 3, "110100", "3"); list.add(org); org = new Org("4", "3", "东城区", 4, "110101", "4"); list.add(org); org = new Org("5", "3", "东城区", 5, "110102", "4"); list.add(org); org = new Org("6", "3", "东城区", 6, "110105", "4"); list.add(org); org = new Org("7", "3", "东城区", 7, "110106", "4"); list.add(org); org = new Org("8", "3", "东城区", 8, "110107", "4"); list.add(org); org = new Org("9", "3", "东城区", 9, "110108", "4"); list.add(org); org = new Org("10", "3", "东城区", 10, "110109", "4"); list.add(org); org = new Org("11", "3", "东城区", 11, "110111", "4"); list.add(org); org = new Org("12", "3", "东城区", 12, "110112", "4"); list.add(org); org = new Org("13", "3", "东城区", 13, "110113", "4"); list.add(org); org = new Org("14", "3", "东城区", 14, "110114", "4"); list.add(org); org = new Org("15", "3", "东城区", 15, "110115", "4"); list.add(org); org = new Org("16", "3", "东城区", 16, "110116", "4"); list.add(org); org = new Org("17", "3", "东城区", 17, "110117", "4"); list.add(org); org = new Org("18", "2", "县", 3, "110200", "3"); list.add(org); org = new Org("19", "18", "密云县", 19, "110228", "4"); list.add(org); org = new Org("20", "18", "延庆县", 20, "110229", "4"); list.add(org); return list; } }
执行结果以下:
{ "nodeId": "2", "nodeName": "北京市", "parentNodeId": "1", "orderNum": 2, "level": 0, "children": [{ "nodeId": "18", "nodeName": "县", "parentNodeId": "2", "orderNum": 3, "level": 0, "children": [{ "nodeId": "19", "nodeName": "密云县", "parentNodeId": "18", "orderNum": 19, "level": 0, "children": [] }, { "nodeId": "20", "nodeName": "延庆县", "parentNodeId": "18", "orderNum": 20, "level": 0, "children": [] }] }, { "nodeId": "3", "nodeName": "市辖区", "parentNodeId": "2", "orderNum": 3, "level": 0, "children": [{ "nodeId": "17", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 17, "level": 0, "children": [] }, { "nodeId": "15", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 15, "level": 0, "children": [] }, { "nodeId": "16", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 16, "level": 0, "children": [] }, { "nodeId": "13", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 13, "level": 0, "children": [] }, { "nodeId": "14", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 14, "level": 0, "children": [] }, { "nodeId": "11", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 11, "level": 0, "children": [] }, { "nodeId": "12", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 12, "level": 0, "children": [] }, { "nodeId": "10", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 10, "level": 0, "children": [] }, { "nodeId": "7", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 7, "level": 0, "children": [] }, { "nodeId": "6", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 6, "level": 0, "children": [] }, { "nodeId": "5", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 5, "level": 0, "children": [] }, { "nodeId": "4", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 4, "level": 0, "children": [] }, { "nodeId": "9", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 9, "level": 0, "children": [] }, { "nodeId": "8", "nodeName": "东城区", "parentNodeId": "3", "orderNum": 8, "level": 0, "children": [] }] }] }
注:该示例中使用了 alibaba 的 fastjson 实现类对象序列化,maven 依赖以下:
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.20</version> </dependency>