Java编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级

来源:互联网 发布:淘宝客服骂人怎么投诉 编辑:程序博客网 时间:2024/05/01 08:22

在平时的开发工作中,经常遇到这样一个场景,在数据库中存储了具有父子关系的数据,需要将这些数据以树形结构的形式在界面上进行展示。本文的目的是提供了一个通用的编程模型,解决将具有父子关系的数据转换成树形结构的问题。如有不正之处,欢迎大家批评指正。

编程模型

我们以北京行政区划为例,讲解整个模型。

北京市:市辖区 县

市辖区:东城区 西城区 朝阳区 丰台区 石景山区 海淀区 门头沟区 房山区 通州区 顺义区 昌平区 大兴区 怀柔区 平谷区

县:密云县 延庆县

UML类图如下:

Tree结构

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
原创粉丝点击