Java編程:將具有父子關系的數據庫表數據轉換為樹形結構,支持無限層級


在平時的開發工作中,經常遇到這樣一個場景,在數據庫中存儲了具有父子關系的數據,需要將這些數據以樹形結構的形式在界面上進行展示。本文的目的是提供了一個通用的編程模型,解決將具有父子關系的數據轉換成樹形結構的問題。如有不正之處,歡迎大家批評指正。
編程模型

我們以北京行政區划為例,講解整個模型。

北京市:市轄區 縣

市轄區:東城區 西城區 朝陽區 豐台區 石景山區 海淀區 門頭溝區 房山區 通州區 順義區 昌平區 大興區 懷柔區 平谷區

縣:密雲縣 延慶縣

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 接口。
---------------------

在平時的開發工作中,經常遇到這樣一個場景,在數據庫中存儲了具有父子關系的數據,需要將這些數據以樹形結構的形式在界面上進行展示。本文的目的是提供了一個通用的編程模型,解決將具有父子關系的數據轉換成樹形結構的問題。如有不正之處,歡迎大家批評指正。
編程模型

我們以北京行政區划為例,講解整個模型。

北京市:市轄區 縣

市轄區:東城區 西城區 朝陽區 豐台區 石景山區 海淀區 門頭溝區 房山區 通州區 順義區 昌平區 大興區 懷柔區 平谷區

縣:密雲縣 延慶縣

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;
    }   
}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101

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);
}

    1
    2
    3
    4
    5
    6
    7
    8
    9

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);
    }

}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80

ITreeNode 接口:

package com.ips.tree;

public interface ITreeNode {
    public String getNodeId();
    public String getNodeName();
    public String getNodeParentId();
    public Integer getOrderNum();
}

    1
    2
    3
    4
    5
    6
    7
    8

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;
    }

}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85

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;
    }

}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66

執行結果如下:

{
    "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": []
        }]
    }]
}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149

注:該示例中使用了 alibaba 的 fastjson 實現類對象序列化,maven 依賴如下:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.20</version>
</dependency>
---------------------
作者:zhiboer
來源:CSDN
原文:https://blog.csdn.net/claram/article/details/54616485
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM