diff --git a/commons/common-util/src/main/java/com/schbrain/common/util/TreeUtil.java b/commons/common-util/src/main/java/com/schbrain/common/util/TreeUtil.java deleted file mode 100644 index 411f09fcab1867166482b06db44189d8cf50427d..0000000000000000000000000000000000000000 --- a/commons/common-util/src/main/java/com/schbrain/common/util/TreeUtil.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.schbrain.common.util; - -import org.apache.commons.collections4.CollectionUtils; - -import java.util.*; -import java.util.function.BiConsumer; -import java.util.function.Function; - -/** - * 树工具类 - */ -public class TreeUtil { - - /** - * 通过列表构建一个树状结构 - * - * @param nodes 节点列表 - * @param idGetMethod 获取当前节点ID的方法 - * @param parentIdGetMethod 获取父节点ID的方法 - * @param setParentMethod 设置子节点列表的方法 - * @param parentId 父节点ID,可以为null - */ - public static List buildTree(List nodes, - Function idGetMethod, - Function parentIdGetMethod, - BiConsumer> setParentMethod, - K parentId) { - if (CollectionUtils.isEmpty(nodes)) { - return nodes; - } - Map> parentGroupMap = new HashMap<>(); - for (T node : nodes) { - K key = parentIdGetMethod.apply(node); - List subNodes = parentGroupMap.getOrDefault(key, new ArrayList<>()); - subNodes.add(node); - parentGroupMap.put(key, subNodes); - } - return buildTree(idGetMethod, setParentMethod, parentId, parentGroupMap); - } - - /** - * 递归通过列表构建一个树状结构 - * - * @param idGetMethod 获取当前节点ID的方法 - * @param setParentMethod 设置子节点列表的方法 - * @param parentId 父节点ID,可以为null - * @param parentGroupMap 存放节点下层节点列表的map - */ - private static List buildTree(Function idGetMethod, - BiConsumer> setParentMethod, - K parentId, Map> parentGroupMap) { - List nodes = parentGroupMap.get(parentId); - if (CollectionUtils.isEmpty(nodes)) { - return Collections.emptyList(); - } - nodes.forEach(item -> setParentMethod.accept(item, buildTree(idGetMethod, setParentMethod, idGetMethod.apply(item), parentGroupMap))); - return nodes; - } - -} - - - - - diff --git a/commons/common-util/src/main/java/com/schbrain/common/util/TreeUtils.java b/commons/common-util/src/main/java/com/schbrain/common/util/TreeUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..0dccc5d189c4949907aec48576d59055849dae14 --- /dev/null +++ b/commons/common-util/src/main/java/com/schbrain/common/util/TreeUtils.java @@ -0,0 +1,60 @@ +package com.schbrain.common.util; + +import org.apache.commons.collections4.CollectionUtils; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Function; + +/** + * Utils to build tree + * + * @author panwangnan + * @since 2023/7/29 + */ +public class TreeUtils { + + public static List buildTree(List nodes, + Function keyExtractor, + Function parentKeyExtractor, + BiConsumer> childrenSetter, + @Nullable K parentId) { + return buildTree(nodes, keyExtractor, parentKeyExtractor, Function.identity(), childrenSetter, parentId); + } + + public static List buildTree(List nodes, + Function keyExtractor, + Function parentKeyExtractor, + Function childMapper, + BiConsumer> childrenSetter, + @Nullable K parentId) { + if (CollectionUtils.isEmpty(nodes)) { + return new ArrayList<>(); + } + Map> parentWithSubNodes = StreamUtils.groupBy(nodes, parentKeyExtractor, true); + if (parentId == null) { + // groupBy 不允许 key 为空,当 parentId 为空时,单独处理下 + List subNodes = StreamUtils.filterToList(nodes, node -> parentKeyExtractor.apply(node) == null); + parentWithSubNodes.put(null, subNodes); + } + return buildTree(keyExtractor, childrenSetter, childMapper, parentWithSubNodes, parentId); + } + + private static List buildTree(Function keyExtractor, + BiConsumer> childrenSetter, + Function childMapper, + Map> parentWithSubNodes, + K parentId) { + List subNodes = parentWithSubNodes.get(parentId); + return StreamUtils.toList(subNodes, subNode -> { + E convertedSubNode = childMapper.apply(subNode); + List children = buildTree(keyExtractor, childrenSetter, childMapper, parentWithSubNodes, keyExtractor.apply(subNode)); + childrenSetter.accept(convertedSubNode, children); + return convertedSubNode; + }); + } + +}