package cn.myflv.data;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* 树结构助手.
*
* @author xin
* @since 2023/3/29 20:54
*/
public class TreeHelper {
/**
* 判断list是否为空
*
* @param list list
* @param <Item> list类型
* @return 是否为空
*/
private static <Item> boolean isEmptyList(List<Item> list) {
return list == null || list.isEmpty();
}
/**
* 从list构建树.
*
* @param list list
* @param toTree 对象转树对象
* @param getKey 对象key获取方法
* @param getParentKey 对象父key获取方法
* @param setChildren 子节点设置方法
* @param <Tree> 树类型
* @param <Node> list类型
* @param <Key> key类型
* @return 树
*/
public static <Tree, Node, Key> List<Tree> fromList(List<Node> list, Function<Node, Tree> toTree,
Function<Node, Key> getKey, Function<Node, Key> getParentKey, BiConsumer<Tree, List<Tree>> setChildren) {
List<Key> keyList = list.stream().map(getKey).filter(Objects::nonNull).distinct().collect(Collectors.toList());
return fromList(list, x -> !keyList.contains(getParentKey.apply(x)), toTree, getKey, getParentKey, setChildren);
}
/**
* 从list构建树.
*
* @param list list
* @param findParent 父节点判断
* @param toTree 对象转树对象
* @param getKey 对象key获取方法
* @param getParentKey 对象父key获取方法
* @param setChildren 子节点设置方法
* @param <Tree> 树类型
* @param <Node> list类型
* @param <Key> key类型
* @return 树
*/
public static <Tree, Node, Key> List<Tree> fromList(List<Node> list, Predicate<Node> findParent,
Function<Node, Tree> toTree, Function<Node, Key> getKey, Function<Node, Key> getParentKey,
BiConsumer<Tree, List<Tree>> setChildren) {
List<Tree> treeList = new ArrayList<>();
List<Node> parentList = list.stream().filter(findParent).collect(Collectors.toList());
if (isEmptyList(parentList)) {
return treeList;
}
Map<Key, List<Node>> parentKeyMap = list.stream().filter(x -> getParentKey.apply(x) != null)
.collect(Collectors.groupingBy(getParentKey));
for (Node node : parentList) {
Tree tree = toTree.apply(node);
Key key = getKey.apply(node);
setChildren.accept(tree, getChildren(key, parentKeyMap, toTree, getKey, setChildren));
treeList.add(tree);
}
return treeList;
}
/**
* 获取子节点.
*
* @param key 对象key
* @param parentKeyMap 对象父key分组
* @param toTree 转树方法
* @param getKey 对象key获取方法
* @param setChildren 设置子节点方法
* @param <Tree> 树类型
* @param <Node> 节点类型
* @param <Key> key类型
* @return 树
*/
private static <Tree, Node, Key> List<Tree> getChildren(Key key, Map<Key, List<Node>> parentKeyMap,
Function<Node, Tree> toTree, Function<Node, Key> getKey, BiConsumer<Tree, List<Tree>> setChildren) {
List<Node> childList = parentKeyMap.get(key);
List<Tree> treeList = new LinkedList<>();
if (isEmptyList(childList)) {
return treeList;
}
for (Node node : childList) {
Tree tree = toTree.apply(node);
Key childKey = getKey.apply(node);
treeList.add(tree);
setChildren.accept(tree, getChildren(childKey, parentKeyMap, toTree, getKey, setChildren));
}
return treeList;
}
/**
* 从树构建list.
*
* @param treeList 树
* @param toNode 树转对象
* @param generateKey 对象key获取方法
* @param setKey 对象key设置方法
* @param getChildren 子节点获取方法
* @param <Tree> 树类型
* @param <Node> list类型
* @param <Key> key类型
* @return list
*/
public static <Tree, Node, Key> List<Node> toList(List<Tree> treeList, Function<Tree, Node> toNode,
Function<Node, Key> generateKey, BiConsumer<Node, Key> setKey, BiConsumer<Node, Key> setParentKey,
Function<Tree, List<Tree>> getChildren) {
List<Node> nodeList = new LinkedList<>();
if (isEmptyList(treeList)) {
return nodeList;
}
for (Tree tree : treeList) {
Node node = toNode.apply(tree);
Key key = generateKey.apply(node);
setKey.accept(node, key);
nodeList.add(node);
List<Tree> childList = getChildren.apply(tree);
nodeList.addAll(getChildren(key, childList, toNode, generateKey, setKey, setParentKey, getChildren));
}
return nodeList;
}
/**
* 从树构建list.
*
* @param treeList 树
* @param toNode 树转对象
* @param generateKey 对象key获取方法
* @param setKey 对象key设置方法
* @param getChildren 子节点获取方法
* @param <Tree> 树类型
* @param <Node> list类型
* @param <Key> key类型
* @return list
*/
private static <Tree, Node, Key> List<Node> getChildren(Key parentKey, List<Tree> treeList,
Function<Tree, Node> toNode, Function<Node, Key> generateKey, BiConsumer<Node, Key> setKey,
BiConsumer<Node, Key> setParentKey, Function<Tree, List<Tree>> getChildren) {
List<Node> nodeList = new LinkedList<>();
if (isEmptyList(treeList)) {
return nodeList;
}
for (Tree tree : treeList) {
Node node = toNode.apply(tree);
Key key = generateKey.apply(node);
setKey.accept(node, key);
setParentKey.accept(node, parentKey);
nodeList.add(node);
List<Tree> childList = getChildren.apply(tree);
nodeList.addAll(toList(childList, toNode, generateKey, setKey, setParentKey, getChildren));
}
return nodeList;
}
}
Java树型数据工具类
评论 (暂无评论)