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

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

编程模型

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

北京市:市辖区 县

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

县:密云县 延庆县

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;

/**
 * 

Title: 树节点

*

Description:一棵树由许多包含父子关系的节点组成

* @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 children = new ArrayList(); //当前节点的子孙节点 private List allChildren = new ArrayList(); 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 getChildren() { return children; } public void setChildren(List children) { this.children = children; } public int getOrderNum() { return orderNum; } public void setOrderNum(int orderNum) { this.orderNum = orderNum; } public List 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 getTree();
    public List 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 treeNodesMap = new HashMap();
    private List treeNodesList = new ArrayList();

    public Tree(List list){
        initTreeNodeMap(list);
        initTreeNodeList();
    }

    private void initTreeNodeMap(List list){
        TreeNode treeNode = null;
        for(ITreeNode item : list){
            treeNode = new TreeNode(item);
            treeNodesMap.put(treeNode.getNodeId(), treeNode);
        }

        Iterator 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 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 getTree() {
        return this.treeNodesList;
    }

    @Override
    public List getRoot() {
        List rootList = new ArrayList();
        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 genOrgList(){
        List list = new ArrayList();

        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 依赖如下:


    com.alibaba
    fastjson
    1.2.20

你可能感兴趣的:(Java编程)