【Easylive】项目常见问题解答(自用&持续更新中...) 汇总版
这是一个 将扁平列表转换为树形结构 的递归方法,常用于处理 分类目录、菜单、部门 等具有父子层级关系的数据。下面逐步解析其逻辑和设计思想。
1. 方法作用
• 输入 :扁平化的分类列表(List<CategoryInfo>
),每个对象包含 categoryId
和 pCategoryId
(父ID)。
• 输出 :树形结构的分类列表,每个节点的子分类挂在 children
属性下。
• 典型场景 :
数据库存储的是一维表结构(每行记录通过 pCategoryId
指向父节点),但前端需要树形结构展示。
2. 参数说明
参数名 | 类型 | 作用 |
---|---|---|
dataList |
List<CategoryInfo> |
扁平化的原始数据列表(包含所有节点,不区分层级)。 |
pid |
Integer |
当前递归层级的父节点ID(首次调用时通常传 0 或 null 表示根节点)。 |
3. 核心逻辑分步解析
(1) 初始化子节点列表
java
List<CategoryInfo> children = new ArrayList<>();
• 为当前层级(pid
的子节点)准备一个空列表。
(2) 遍历所有节点
java
for (CategoryInfo m : dataList) {
// 检查当前节点是否属于当前父节点
if (m.getCategoryId() != null && m.getpCategoryId() != null && m.getpCategoryId().equals(pid)) {
// 递归处理子节点
m.setChildren(convertLine2Tree(dataList, m.getCategoryId()));
children.add(m);
}
}
• 条件判断 :
找到所有 pCategoryId == pid
的节点(即父节点是 pid
的节点)。
• 递归调用 :
对每个符合条件的节点,继续查找其子节点(以 m.getCategoryId()
作为新的 pid
)。
• 构建树形 :
将子节点列表设置到当前节点的 children
属性中。
(3) 返回结果
java
return children;
• 返回当前层级的所有子节点(已递归包含所有后代节点)。
4. 示例演示
假设原始数据
categoryId | pCategoryId | name |
---|---|---|
1 | 0 | 电子产品 |
2 | 0 | 服装 |
3 | 1 | 手机 |
4 | 1 | 电脑 |
5 | 3 | 智能手机 |
调用过程
-
首次调用 :
convertLine2Tree(dataList, 0)
• 找到根节点(
pCategoryId=0
):[电子产品, 服装]
• 对
电子产品
递归:◦ 找到子节点(
pCategoryId=1
):[手机, 电脑]
◦ 对
手机
递归:◦ 找到子节点(
pCategoryId=3
):[智能手机]
◦
智能手机
无子节点,递归终止。•
服装
无子节点,递归终止。 -
最终树形结构:
json[ { "categoryId": 1, "name": "电子产品", "children": [ { "categoryId": 3, "name": "手机", "children": [ { "categoryId": 5, "name": "智能手机", "children": [] } ] }, { "categoryId": 4, "name": "电脑", "children": [] } ] }, { "categoryId": 2, "name": "服装", "children": [] } ]
5. 关键点分析
(1) 递归终止条件
• 隐含在 if
条件中:当没有节点的 pCategoryId
匹配当前 pid
时,递归结束。
• 无需显式判断,因为 children
会返回空列表。
(2) 时间复杂度
• 最坏情况 :O(n²)(每个节点遍历整个列表)。
优化方案 :
• 先用 Map<Integer, List<CategoryInfo>>
按 pCategoryId
分组,可将时间优化到 O(n)。
• 示例:
java Map<Integer, List<CategoryInfo>> groupMap = dataList.stream() .collect(Collectors.groupingBy(CategoryInfo::getpCategoryId));
(3) 注意事项
• 数据需有序 :若原始数据是乱序的,可能漏掉深层节点。建议先按层级排序。
• 避免循环引用 :如 A→B→C→A
会导致无限递归。需确保数据无环。
6. 方法优化建议
(1) 使用 Map 加速查找
java
private List<CategoryInfo> convertLine2Tree(List<CategoryInfo> dataList, Integer pid) {
// 先按父ID分组
Map<Integer, List<CategoryInfo>> groupMap = dataList.stream()
.collect(Collectors.groupingBy(CategoryInfo::getpCategoryId));
List<CategoryInfo> children = groupMap.getOrDefault(pid, new ArrayList<>());
for (CategoryInfo m : children) {
m.setChildren(convertLine2Tree(dataList, m.getCategoryId()));
}
return children;
}
(2) 支持空父节点
java
if (pid == null) {
pid = 0; // 默认根节点ID
}
7. 总结
• 核心思想 :通过递归将扁平列表转换为树形结构。
• 适用场景 :任何需要父子层级展示的数据(如分类、菜单、评论回复)。
• 优化方向 :使用 Map
分组减少遍历次数,确保数据无环。