Java编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级
来源:互联网 发布:淘宝客服骂人怎么投诉 编辑:程序博客网 时间:2024/05/01 08:22
在平时的开发工作中,经常遇到这样一个场景,在数据库中存储了具有父子关系的数据,需要将这些数据以树形结构的形式在界面上进行展示。本文的目的是提供了一个通用的编程模型,解决将具有父子关系的数据转换成树形结构的问题。如有不正之处,欢迎大家批评指正。
编程模型
我们以北京行政区划为例,讲解整个模型。
北京市:市辖区 县
市辖区:东城区 西城区 朝阳区 丰台区 石景山区 海淀区 门头沟区 房山区 通州区 顺义区 昌平区 大兴区 怀柔区 平谷区
县:密云县 延庆县
UML类图如下:
TreeNode:定义树的节点对象
- nodeId:树节点Id。
- nodeName:树节点名称。
- parentNodeId:树节点父Id。
- orderNum:节点在树中的排序号,在同一节点下进行排序。
- level:当前树节点所在的层级,根节点为第一层。
- parent:当前树节点的父节点。
- children:当前树节点的儿子节点。
- allChildren:当前树节点的子孙节点。
ITree:定义树对象要实现的方法。
- getTree():以 List 形式返回树的所有的 TreeNode 对象。
- getRoot():以 List 形式返回树的根节点,可能是一个或者多个。
- getTreeNode(String nodeId):根据 nodeId 返回对应的 TreeNode 对象。
Tree:实现 ITree 接口,提供树的完整功能。
- getTree():以 List 形式返回树的所有的 TreeNode 对象。
- getRoot():以 List 形式返回树的根节点,可能是一个或者多个。
- getTreeNode(String nodeId):根据 nodeId 返回对应的 TreeNode 对象。
ITreeNode:定义模板方法,构造树形结构的类要实现该接口,Tree 通过调用该接口中的方法获取 nodeId nodeName parentNodeId orderNum 数据。
- getNodeId():获取树节点Id。
- getNodeName():获取树节点名称。
- getParentNodeId():获取树节点父Id。
- getOrderNum():获取节点在树中的排序号,在同一节点下进行排序。
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>
1 0
- Java编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级
- JavaScript将具有父子关系的原始数据格式化成树形结构数据
- js将有父子关系的数据转换成树形结构数据
- 将树形结构的数据转换为二维数组 (续 PHP非递归方式实现无限分类(转载))
- yx-树形结构展示,父子关系显示为完整树形
- 无限层级且乱序的树形结构数据的整理,利用HashMap减少遍历次数
- java、js中实现无限层级的树形结构(类似递归)
- Java、JS中实现无限层级的树形结构(类似递归)
- 由具有父子关系数据得到其树结构
- Web中树形数据(层级关系数据)的实现—以行政区树为例
- Web中树形数据(层级关系数据)的实现—以行政区树为例(二)
- Web中树形数据(层级关系数据)的实现―以行政区树为例
- 将给定格式的线性结构转换为树形结构
- 根据数据的父子关系创建树形结构并实现遍历
- 根据数据的父子关系创建树形结构并实现遍历
- 根据数据的父子关系创建树形结构并实现遍历
- 将excel树形结构的数据导入数据库
- 将数据库读取的平级数据转换成父子孙结构
- PowerDesigner打印错误
- Google登录 iOS
- 基本编程 honker
- MySQL - 分组,排序,取出单独的年月日
- java实现GET/POST请求
- Java编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级
- ubuntu16.04 vim-gnome
- windows yii2 advanced默认登录配置
- 树状数组—改段求点
- adb ——shell
- zigbee编译错误汇总(一)
- APP开发实战152-Android使用UncaughtExceptionHandler处理异常
- dubbo的使用2
- sklearn基本用法----SVM