在權限管理、組織架構、CMS 分類等系統中,多層目錄樹是核心資料結構。本文展示一套基於 Java 的完整實現:Node 節點實體、NodeStore 持久化抽象、Tree 樹構建與操作入口,支援讀取、序列化、排序與路徑計算,為後續擴展增刪改移奠定基礎。
Serializable、Comparable。findByType、add、update、delete、move。build() 將平面列表轉為樹、getNodeById() 查詢、後續擴展寫操作並透過 NodeStore 持久化。
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 略
}
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 略
}
HashMap 索引,無需遞歸查找父節點。addChild 同時設定 child.parent 與 parent.children,保證樹結構一致性。NodeStore 介面隔離儲存細節,切換 DB/XML 零侵入業務邏輯。Comparable + 遞歸排序,getPathName 遞歸拼裝完整路徑,前端直用無需二次處理。toJson() 遞歸生成 {id, name, children:[...]},完美配合 zTree、jstree 等前端組件。Tree 新增 addNode、deleteNode、moveNode,內部操作記憶體樹並委派 NodeStore 持久化。ReadWriteLock 保護 nodeHolder 與樹結構,支援高併發讀寫。Node 新增 loaded 標記,首次訪問子節點時再從 NodeStore 查詢。完整源碼已上傳,可直接整合至專案作為目錄樹基礎設施。