All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.power4j.coca.kit.common.collection.tree.TreeUtil Maven / Gradle / Ivy

The newest version!
/*
 *  Copyright 2021 ChenJun ([email protected] & https://github.com/John-Chan)
 *
 *  Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  

* http://www.gnu.org/licenses/lgpl.html *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.power4j.coca.kit.common.collection.tree; import lombok.Builder; import lombok.Getter; import lombok.experimental.UtilityClass; import org.apache.commons.lang3.ObjectUtils; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; /** * @author CJ ([email protected]) * @date 2022/1/19 * @since 1.0 */ @UtilityClass public class TreeUtil { /** * 在给定的集合中查找根节点 * @param source 数据源 * @param idGetter ID取值方法 * @param pidGetter PID取值方法 * @param ID 类型 * @param 对象 * @return 返回根节点MAP */ public Map findAncestors(Map source, Function idGetter, Function pidGetter) { Map output = new HashMap<>(8); Set skipSet = new HashSet<>(8); for (T node : source.values()) { if (skipSet.contains(idGetter.apply(node))) { continue; } T ancestor = findAncestor(source, node, skipSet, idGetter, pidGetter); output.put(idGetter.apply(ancestor), ancestor); } return output; } T findAncestor(Map source, T child, Set skipSet, Function idGetter, Function pidGetter) { T parent = source.get(pidGetter.apply(child)); if (Objects.nonNull(parent)) { skipSet.add(idGetter.apply(child)); return findAncestor(source, parent, skipSet, idGetter, pidGetter); } return child; } /** * 填充子级 * @param source 数据源 * @param roots 根节点 * @param nodeOp 各种操作函数 * @param ID 类型 * @param 节点类型 */ public void fetch(Collection source, Collection roots, NodeOp nodeOp) { Map sourceMap = source.stream() .collect(Collectors.toMap(nodeOp.idGetter, Function.identity(), (x, y) -> y, LinkedHashMap::new)); Map rootMap = roots.stream() .collect(Collectors.toMap(nodeOp.idGetter, Function.identity(), (x, y) -> y, LinkedHashMap::new)); fetch(sourceMap, rootMap, nodeOp); } /** * 填充子级 * @param source 数据源 * @param roots 根节点 * @param nodeOp 各种操作函数 * @param ID 类型 * @param 节点类型 */ public void fetch(Map source, Map roots, NodeOp nodeOp) { if (roots.isEmpty()) { return; } for (T node : source.values()) { if (null == node) { continue; } final ID id = Objects.requireNonNull(nodeOp.idGetter.apply(node)); if (roots.containsKey(id)) { continue; } final ID parentId = nodeOp.pidGetter.apply(node); final T parentNode = Optional.ofNullable(roots.get(parentId)).orElseGet(() -> source.get(parentId)); if (null != parentNode) { nodeOp.childConsumer.accept(parentNode, node); } } } /** * 迭代树节点 * @param roots 根节点 * @param accessOp 各种操作函数 * @param consumer 节点消费函数 * @param ID 类型 * @param 节点类型 */ public void treeWalk(Collection roots, AccessOp accessOp, Consumer consumer) { for (final T node : roots) { consumer.accept(node); Collection children = accessOp.childrenGetter.apply(node); if (ObjectUtils.isNotEmpty(children)) { treeWalk(children, accessOp, consumer); } } } /** * 树节点转list * @param roots 根节点 * @param accessOp 各种操作函数 * @param ID 类型 * @param 节点类型 * @return 返回节点MAP */ public List flatten(Collection roots, AccessOp accessOp) { List list = new ArrayList<>(roots.size()); treeWalk(roots, accessOp, list::add); return list; } @Getter @Builder public static class NodeOp { /** * 取ID的方法 */ private final Function idGetter; /** * 取PID的方法 */ private final Function pidGetter; /** * 添加子元素的方法 */ private final BiConsumer childConsumer; } @Getter @Builder public static class AccessOp { /** * 取ID的方法 */ private final Function idGetter; /** * 取PID的方法 */ private final Function pidGetter; /** * 访问子元素列表的方法 */ private final Function> childrenGetter; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy