/**
- 遍历原始数据列表,按照给定的父ID获取函数对节点进行分组,构建一个以父ID为键、子节点列表为值的映射表。
- 这样可以方便地根据节点的子ID快速找到其所有子节点。
- 初始化一个空的结果列表,用于存放最终形成的树形结构。
- 遍历原始数据列表中的每个节点:
- a. 使用子ID获取函数获取当前节点的子ID。
- b. 从映射表中查找与当前节点子ID对应的子节点列表。如果存在且非空,说明当前节点有子节点,
-
则使用给定的子节点设置消费者将子节点列表赋给当前节点。 - c. 使用父ID获取函数获取当前节点的父ID。
- d. 根据传入的根节点标识判断当前节点是否应被加入结果列表:
-
- 如果根节点标识为null,表示返回整个树形结构,因此将所有节点都加入结果列表; -
- 否则,只有当当前节点的父ID等于根节点标识时,才将当前节点加入结果列表。 - 最终返回构建好的树形结构列表。
/
/*
-
将数据转换为树状数据
-
@param list 原始数据列表
-
@param rootTrait 根节点标识(如果为null,则返回所有节点组成的树)
-
@param parentValueGetter 获取节点父ID的函数
-
@param childValueGetter 获取节点子ID的函数
-
@param childSetter 设置节点子节点列表的消费者
-
@param 节点类型
-
@param ID类型
-
@return 树形数据 */ public static <T, R> List buildTree(List list, R rootTrait, Function<T, R> parentValueGetter, Function<T, R> childValueGetter, BiConsumer<T, List> childSetter) {
Map<R, List> nodesByParentId = list.stream() .collect(Collectors.groupingBy(parentValueGetter));
List result = new ArrayList<>(); for (T node : list) { R nodeId = childValueGetter.apply(node); List children = nodesByParentId.get(nodeId);
if (CollUtil.isNotEmpty(children)) { childSetter.accept(node, children); } R parentNodeId = parentValueGetter.apply(node); if (rootTrait == null || Objects.equals(parentNodeId, rootTrait)) { result.add(node); }}
return result; }
-