通用节点树构建、通用树名称搜索
package cn.crservice.ic.bp.util;
import java.util.Comparator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 树
*
* @author seliote
* @since 2022-07-15
*/
public class TreeUtils {
public static <T, I> List<T> build(List<T> list,
Function<T, I> getId,
Function<T, I> getParentId,
Comparator<T> comparator,
BiConsumer<T, List<T>> setSub) {
var tree = rootList(list, getId, getParentId);
sortList(tree, comparator);
tree.forEach(n -> build(n, list, getId, getParentId, comparator, setSub));
return tree;
}
private static <T, I> List<T> rootList(List<T> list,
Function<T, I> getId,
Function<T, I> getParentId) {
var idSet = list.stream().map(getId).collect(Collectors.toSet());
var parentIdSet = list.stream().map(getParentId).collect(Collectors.toSet());
parentIdSet.removeAll(idSet);
return list.stream().filter(i -> parentIdSet.contains(getParentId.apply(i))).collect(Collectors.toList());
}
private static <T> void sortList(List<T> list, Comparator<T> comparator) {
list.sort(comparator);
}
private static <T, I> void build(T node,
List<T> list,
Function<T, I> getId,
Function<T, I> getParentId,
Comparator<T> comparator,
BiConsumer<T, List<T>> setSub) {
var id = getId.apply(node);
var sub = list.stream().filter(i -> id.equals(getParentId.apply(i))).collect(Collectors.toList());
if (sub.size() != 0) {
sortList(sub, comparator);
setSub.accept(node, sub);
sub.forEach(s -> build(s, list, getId, getParentId, comparator, setSub));
}
}
public static <T> void filterTreeByName(@NonNull List<T> tree,
@NonNull Function<T, List<T>> getSub,
@NonNull Function<T, String> getName,
@NonNull String searchName,
@NonNull Boolean reserveChild) {
if (StringUtils.isEmpty(searchName)) {
return;
}
for (Iterator<T> iterator = tree.iterator(); iterator.hasNext(); ) {
T n = iterator.next();
String name = getName.apply(n);
if (reserveChild && !StringUtils.isEmpty(name) && name.contains(searchName)) {
continue;
}
List<T> sub = getSub.apply(n);
if (sub != null && sub.size() != 0) {
filterTreeByName(sub, getSub, getName, searchName, reserveChild);
}
if ((sub == null || sub.size() == 0) && (StringUtils.isEmpty(name) || !name.contains(searchName))) {
iterator.remove();
}
}
}
}
用法
var tree = TreeUtils.build(list, Menu::getId, Menu::getParentId, Comparator.comparing(Menu::getOrderNo), Menu::setSub);