首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 實現多層目錄樹結構:從平面節點到樹形架構的完整設計

     編輯:Java 相關知識

在權限管理、組織架構、CMS 分類等系統中,多層目錄樹是核心資料結構。本文展示一套基於 Java 的完整實現:Node 節點實體、NodeStore 持久化抽象、Tree 樹構建與操作入口,支援讀取、序列化、排序與路徑計算,為後續擴展增刪改移奠定基礎。

核心設計理念

  • Node:純記憶體節點,含屬性(id、name、type…)與樹關係(parent、children),實現 Serializable、Comparable。
  • NodeStore:持久化介面,屏蔽底層儲存細節(DB、XML、NoSQL),提供 findByType、add、update、delete、move。
  • Tree:樹操作門面,負責 build() 將平面列表轉為樹、getNodeById() 查詢、後續擴展寫操作並透過 NodeStore 持久化。

類別圖:Node、NodeStore、Tree 關係

Node.java 核心代碼解析

public class Node implements Serializable, Comparable<Node> {
    private Integer id, parentId;
    private String name, description, type;
    private Node parent;
    private List<Node> children;

    // 建立雙向父子關係
    public void addChild(Node child) {
        if (child == null) return;
        child.setParent(this);
        if (children == null) children = new ArrayList<>();
        children.add(child);
    }
    public void removeChild(Node child) {
        if (child == null || children == null) return;
        child.setParent(null);
        children.remove(child);
    }

    // 遞歸取得完整路徑
    public String getPathName(String sep) {
        String path = getName();
        if (getParent() != null) path = getParent().getPathName(sep) + sep + path;
        return path;
    }
    public boolean isRootNode() { return getParentId() == -1; }
    public boolean isEndNode() { return children == null || children.isEmpty(); }

    // 遞歸排序:先序遍歷對所有子樹排序
    public void sortAllChildren() {
        if (isEndNode()) return;
        Collections.sort(children);
        for (Node c : children) c.sortAllChildren();
    }

    // 序列化為 JSONObject(含遞歸 children 陣列)
    public JSONObject toJson() { /* ... */ }

    @Override public int compareTo(Node o) { return this.id.compareTo(o.id); }
    // getter/setter 略
}

Tree.java 核心建樹邏輯

public class Tree<T extends Node> {
    private String type;
    private Node root;
    private final Map<Integer, T> nodeHolder = new HashMap<>();
    private NodeStore<T> nodeStore;

    public void build() throws TreeException {
        List<T> nodes = nodeStore.findByType(type);
        if (nodes == null || nodes.isEmpty()) return;

        // 1. 識別根節點、填充 nodeHolder
        for (T n : nodes) {
            if (n.isRootNode()) this.root = n;
            nodeHolder.put(n.getId(), n);
        }
        if (root == null) throw new TreeException("no root node found.");

        // 2. 建立父子關係
        for (T n : nodes) {
            if (n.isRootNode()) continue;
            Node parent = getNodeById(n.getParentId());
            if (parent == null) throw new TreeException("parent missing for " + n.getId());
            parent.addChild(n);
        }
        // 3. 全樹排序
        root.sortAllChildren();
    }

    public Node getRoot() { return root; }
    public Node getNodeById(Integer id) { return nodeHolder.get(id); }
    // setter 略
}

關鍵設計亮點

  1. 平面轉樹 O(N):兩次遍歷(識別根 + 掛載子節點),配合 HashMap 索引,無需遞歸查找父節點。
  2. 雙向鏈路:addChild 同時設定 child.parent 與 parent.children,保證樹結構一致性。
  3. 可擴展持久化:NodeStore 介面隔離儲存細節,切換 DB/XML 零侵入業務邏輯。
  4. 內建排序與路徑:Comparable + 遞歸排序,getPathName 遞歸拼裝完整路徑,前端直用無需二次處理。
  5. JSON 序列化:toJson() 遞歸生成 {id, name, children:[...]},完美配合 zTree、jstree 等前端組件。

後續擴展方向

  • 在 Tree 新增 addNode、deleteNode、moveNode,內部操作記憶體樹並委派 NodeStore 持久化。
  • 引入 ReadWriteLock 保護 nodeHolder 與樹結構,支援高併發讀寫。
  • 大數據量時採用「虛擬樹」或「延遲加載」:Node 新增 loaded 標記,首次訪問子節點時再從 NodeStore 查詢。

完整源碼已上傳,可直接整合至專案作為目錄樹基礎設施。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved