
com.power4j.coca.kit.common.collection.tree.TreeNodeUtil Maven / Gradle / Ivy
/*
* 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 com.power4j.coca.kit.common.collection.tree.domain.Node;
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.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* @author CJ ([email protected])
* @date 2022/5/9
* @since 2022.0.3
*/
@UtilityClass
public class TreeNodeUtil {
/**
* 迭代树节点
* @param roots 根节点
* @param consumer 节点消费函数
* @param ID 类型
* @param Node 子类
*/
public > void treeWalk(Collection extends N> roots, Consumer super N> consumer) {
for (final N node : roots) {
consumer.accept(node);
List children = node.getChildren();
if (ObjectUtils.isNotEmpty(children)) {
treeWalk(children, consumer);
}
}
}
/**
* 根据属性排序
* @param list 根节点
* @param keyExtractor 属性取值函数
* @param ID 类型
* @param Node 子类
*/
public static , U extends Comparable super U>> void sortNodes(final List list,
final Function super N, ? extends U> keyExtractor) {
list.sort(Comparator.comparing(keyExtractor));
for (N node : list) {
final List children = node.getChildren();
if (ObjectUtils.isNotEmpty(children)) {
sortNodes(children, keyExtractor);
}
}
}
/**
* 树节点转list
* @param roots 根节点
* @param ID 类型
* @param Node 子类
* @return 返回节点MAP
*/
public > List flatten(List roots) {
List list = new ArrayList<>(roots.size());
treeWalk(roots, list::add);
return list;
}
/**
* 填充子级
* @param source 数据源
* @param roots 根节点
* @param ID 类型
* @param Node 子类
*/
public > void fetch(Map source, Map roots) {
if (roots.isEmpty()) {
return;
}
for (N node : source.values()) {
if (null == node) {
continue;
}
final ID id = Objects.requireNonNull(node.getId());
if (roots.containsKey(id)) {
continue;
}
final ID parentId = node.getParentId();
final N parentNode = Optional.ofNullable(roots.get(parentId)).orElseGet(() -> source.get(parentId));
if (null != parentNode) {
parentNode.appendChild(node);
}
}
}
/**
* 转换为其他类型,无接口依赖
* @param src 数据源
* @param op 转换所需各种函数
* @param dist 用于保存结果
* @param ID 类型
* @param 原类型
* @param 目标类型
*/
public , U> void convert(Collection extends N> src, ConvertOp op,
Collection super U> dist) {
for (N node : src) {
final U target = op.objectConvert.apply(node);
dist.add(target);
final List children = node.getChildren();
if (ObjectUtils.isNotEmpty(children)) {
final List list = new ArrayList<>(2);
convert(children, op, list);
op.childSetter.accept(target, list);
}
}
}
/**
* 转换为其他类型,无接口依赖
* @param src 数据源
* @param op 转换所需各种函数
* @param ID 类型
* @param 原类型
* @param 目标类型
* @return 返回转换后的列表
*/
public , U> List convertToList(Collection extends N> src, ConvertOp op) {
List list = new ArrayList<>(2);
convert(src, op, list);
return list;
}
@Getter
@Builder
public static class ConvertOp {
/**
* 取ID的方法
*/
private final Function super S, ? extends T> objectConvert;
/**
* 添加子元素的方法
*/
private final BiConsumer super T, Collection> childSetter;
}
}