1. 项目背景与核心价值
在软件开发中,树形结构数据的处理是个高频需求场景。无论是后台管理系统的多级菜单、社区平台的多层评论回复,还是企业组织架构中的部门层级关系,本质上都是对父子关系数据的递归操作。我经历过至少7个需要处理这类数据的项目,每次都要重新实现一套相似的逻辑,直到后来封装了这个通用工具类。
这个工具类的核心价值在于:
- 统一处理三种常见树形结构(菜单/评论/部门)
- 提供标准化的树形构建、节点查找、路径追踪等方法
- 内置性能优化策略,避免递归导致的堆栈溢出
- 支持灵活的扩展点,适配不同业务场景的特殊需求
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据结构设计与实现
2.1 基础模型定义
首先需要抽象出树节点的通用属性:
java复制public class TreeNode<T> {
private String id; // 节点ID
private String parentId; // 父节点ID
private Integer level; // 节点层级(可选)
private Integer sort; // 同级排序权重
private Boolean isLeaf; // 是否叶子节点
private T extraData; // 泛型扩展字段
private List<TreeNode<T>> children = new ArrayList<>();
// getters/setters...
}
关键设计点:使用泛型
T存储业务扩展字段,这样既能保持工具类的通用性,又能承载菜单/评论/部门各自的特殊属性
2.2 三种场景的适配处理
虽然数据结构相似,但不同场景有特殊需求:
-
菜单树:
- 需要处理权限过滤(visible字段)
- 需要支持路由元数据(meta)
- 叶子节点通常是可点击的菜单项
-
评论树:
- 需要记录回复对象(replyTo)
- 可能需要分页加载子评论
- 常需要计算点赞数等统计字段
-
部门树:
- 需要维护全路径(path)便于快速查询
- 涉及人员数量统计
- 可能有特殊的权限隔离逻辑
通过策略模式实现场景适配:
java复制public interface TreeStrategy<T> {
boolean isVisible(TreeNode<T> node); // 节点可见性判断
void processNode(TreeNode<T> node); // 节点后置处理
Comparator<TreeNode<T>> getComparator(); // 子节点排序规则
}
3. 核心算法实现
3.1 列表转树形结构
这是最基础也是最关键的方法,将平面列表转换为嵌套树形结构:
java复制public <T> List<TreeNode<T>> buildTree(
List<T> rawList,
Function<T, String> idGetter,
Function<T, String> parentIdGetter,
TreeStrategy<T> strategy) {
// 1. 数据预处理
Map<String, TreeNode<T>> nodeMap = rawList.stream()
.map(item -> {
TreeNode<T> node = new TreeNode<>();
// 属性映射...
return node;
})
.collect(Collectors.toMap(TreeNode::getId, Function.identity()));
// 2. 构建树形关系
List<TreeNode<T>> roots = new ArrayList<>();
nodeMap.values().forEach(node -> {
if (StringUtils.isEmpty(node.getParentId())) {
roots.add(node);
} else {
TreeNode<T> parent = nodeMap.get(node.getParentId());
if (parent != null) {
parent.getChildren().add(node);
}
