|
|
@@ -10,6 +10,9 @@ import lombok.NoArgsConstructor;
|
|
|
import org.dromara.common.core.utils.reflect.ReflectUtils;
|
|
|
|
|
|
import java.util.List;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
|
import java.util.stream.Stream;
|
|
|
|
|
|
@@ -60,6 +63,38 @@ public class TreeBuildUtils extends TreeUtil {
|
|
|
return TreeUtil.build(list, parentId, DEFAULT_CONFIG, nodeParser);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 构建多根节点的树结构(支持多个顶级节点)
|
|
|
+ *
|
|
|
+ * @param list 原始数据列表
|
|
|
+ * @param getId 获取节点 ID 的方法引用,例如:node -> node.getId()
|
|
|
+ * @param getParentId 获取节点父级 ID 的方法引用,例如:node -> node.getParentId()
|
|
|
+ * @param parser 树节点属性映射器,用于将原始节点 T 转为 Tree 节点
|
|
|
+ * @param <T> 原始数据类型(如实体类、DTO 等)
|
|
|
+ * @param <K> 节点 ID 类型(如 Long、String)
|
|
|
+ * @return 构建完成的树形结构(可能包含多个顶级根节点)
|
|
|
+ */
|
|
|
+ public static <T, K> List<Tree<K>> buildMultiRoot(List<T> list, Function<T, K> getId, Function<T, K> getParentId, NodeParser<T, K> parser) {
|
|
|
+ if (CollUtil.isEmpty(list)) {
|
|
|
+ return CollUtil.newArrayList();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 提取所有节点 ID,用于后续判断哪些节点为根节点(即 parentId 不在其中)
|
|
|
+ Set<K> allIds = StreamUtils.toSet(list, getId);
|
|
|
+
|
|
|
+ // 筛选出所有 parentId 不在 allIds 中的节点,这些节点的 parentId 可认为是根节点
|
|
|
+ Set<K> rootParentIds = list.stream()
|
|
|
+ .map(getParentId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .filter(pid -> !allIds.contains(pid))
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+
|
|
|
+ // 使用流处理,遍历每个顶级 parentId,构建对应树,并合并为一个列表返回
|
|
|
+ return rootParentIds.stream()
|
|
|
+ .flatMap(rootParentId -> TreeUtil.build(list, rootParentId, parser).stream())
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 获取节点列表中所有节点的叶子节点
|
|
|
*
|