業務系統中部門架構、菜單導航、商品分類、地區劃分本質都是樹形結構。它們共享同一組核心屬性:id、name、parentId。本文提供一套零侵入、泛型通用的樹構建方案:定義接口 + 工具類遞歸構建,一次編寫,到處復用。
TreeObjectpublic interface TreeObject {
Object getId(); void setId(Object id);
Object getParentId(); void setParentId(Object parentId);
String getName(); void setName(String name);
List getChildren(); void setChildren(List children);
}
設計要點:
Object 類型支援 Long/String/Integer 等多種 IDTreeUtil 核心邏輯提供三種構建入口,覆蓋不同業務場景:
getChildTreeObjects(list, parentId)getChildTreeObjects(list) ⭐ 推薦public List<TreeObject> getChildTreeObjects(List<TreeObject> list) {
// 1. 分離頂層節點(parentId 為 null/空)與子節點
// 2. 建立 ID→對象映射表,O(1) 查找父節點是否存在
// 3. 將孤兒節點(父ID不在列表中)提升為頂層節點
// 4. 遍歷頂層節點,遞歸掛載子節點
}
健壯性亮點:自動處理「髒數據」(父節點缺失、頂層節點非空等邊界情況)。
getChildTreeObjects(list, parentId, prefix)"│ " → "│ │ ")@ApiModel("菜單樹對象")
public class MenuTreeDto implements Serializable, TreeObject {
@ApiModelProperty("菜單ID") private String id;
@ApiModelProperty("菜單名稱") private String menuName;
@ApiModelProperty("父節點ID") private String parentId;
@ApiModelProperty("子菜單") private List<MenuTreeDto> children;
// ... 其他業務字段:menuCode, permission, iconcls, sortNo 等
// 接口方法實現(略)
@Override public Object getId() { return id; }
@Override public void setId(Object id) { this.id = (String) id; }
// ...
}
List<MenuTreeDto> dtoList = BeanMapper.mapList(menuList, MenuTreeDto.class);
if (CollectionUtils.isNotEmpty(dtoList)) {
TreeUtil treeUtil = new TreeUtil();
// 方案 A:指定父ID(如 parentId="0" 為頂級)
List<MenuTreeDto> treeList = treeUtil.getChildTreeObjects(dtoList, "0");
// 方案 B:自動識別根節點(無需傳 parentId)
// List<MenuTreeDto> treeList = treeUtil.getChildTreeObjects(dtoList);
return treeList;
}

{
"success": true,
"data": [
{
"id": "1", "menuName": "系統管理", "parentId": "0",
"children": [
{"id": "2", "menuName": "用戶管理", "parentId": "1", "children": null},
{"id": "3", "menuName": "部門管理", "parentId": "1", "children": null}
]
},
{
"id": "9", "menuName": "調度中心", "parentId": "0",
"children": [...]
}
]
}
| 場景 | 優化方案 |
|---|---|
| 數據量 > 10 萬 | 改用 Map<Id, Node> + 單次遍歷構建,時間複雜度 O(N) |
| 頻繁讀寫 | 引入 Nested Set 或 Closure Table 數據庫模型 |
| 前端樹組件 | 直接返回此 JSON,配合 Element UI / Ant Design Tree 組件零適配 |
| 權限過濾 | 構建前先按權限過濾列表,再構建樹 |