这个一个可以将任何存在上下级关系的数据组装成普通树形结构的工具类,可以在不改变原始数据结构的情况下处理原始数据的树形关系。
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class TreeUtils {
private TreeUtils() {
throw new IllegalStateException("Utility class");
}
/**
* 变换列表
*
* @param collection 收藏
* @return {@link List}<{@link R}>
*/
public static <T, R extends TreeInterface<T>> List<R> transformList(Collection<R> collection) {
if (CollectionUtils.isEmpty(collection)) {
return new ArrayList<>();
}
List<R> result = new ArrayList<>();
Stack<R> stack = new Stack<>();
stack.addAll(collection);
while (!stack.isEmpty()) {
R pop = stack.pop();
result.add(pop);
if (!CollectionUtils.isEmpty(pop.getChildren())) {
stack.addAll(pop.getChildren());
}
}
return result;
}
/**
* 变换列表
*
* @param collection 收藏
* @param consumer 消费者
*/
public static <T, R extends TreeInterface<T>> void transformList(Collection<R> collection, Consumer<R> consumer) {
if (CollectionUtils.isEmpty(collection)) {
return;
}
Stack<R> stack = new Stack<>();
stack.addAll(collection);
while (!stack.isEmpty()) {
R pop = stack.pop();
consumer.accept(pop);
if (!CollectionUtils.isEmpty(pop.getChildren())) {
stack.addAll(pop.getChildren());
}
}
}
/**
* 获取树
*
* @param collection 收藏
* @return {@link List}<{@link TreeDefault}<{@link T}>>
*/
public static <T> List<TreeDefault<T>> getTree(Collection<TreeParam<T>> collection) {
return getTree(collection, () -> TreeDefault.<T>builder().build());
}
/**
* 获取树
*
* @param collection 收藏
* @param clazz 克拉兹
* @return {@link List}<{@link R}>
*/
public static <T, R extends TreeInterface<T>> List<R> getTree(Collection<TreeParam<T>> collection,
Class<R> clazz) {
return getTree(collection, () -> getNewInstance(clazz));
}
/**
* 获取树
*
* @param collection 收藏
* @param supplier 供应商
* @return {@link List}<{@link R}>
*/
public static <T, R extends TreeInterface<T>> List<R> getTree(Collection<TreeParam<T>> collection,
Supplier<R> supplier) {
if (CollectionUtils.isEmpty(collection)) {
return null;
}
Map<String, Set<String>> node = new HashMap<>();//记录节点关系
Map<String, List<T>> nodeParentData = new HashMap<>();//记录节点字段
Map<String, List<T>> nodeData = new HashMap<>();//记录节点字段
collection.forEach(item -> {
String key = item.getKey();
String nodeParentDataKey = key;
if (StringUtils.isNotBlank(item.getParentKey())) {
nodeParentDataKey = key + item.getParentKey();
}
List<T> values = nodeParentData.computeIfAbsent(nodeParentDataKey, k -> new ArrayList<>());
values.add(item.getData());
List<T> nodeDataValues = nodeData.computeIfAbsent(key, k -> new ArrayList<>());
nodeDataValues.add(item.getData());
if (StringUtils.isBlank(item.getParentKey())) {//根对象
node.put(key, null);
} else {
Set<String> parents = node.computeIfAbsent(key, k -> new HashSet<>());
parents.add(item.getParentKey());
}
});
List<R> treeDTO = new ArrayList<>();
Iterator<Map.Entry<String, Set<String>>> iterator = node.entrySet().iterator();
//提取根级节点数据
Set<String> parentIds = new HashSet<>(node.keySet());
while (iterator.hasNext()) {
Map.Entry<String, Set<String>> next = iterator.next();
String key = next.getKey();
Set<String> value = next.getValue();
if (value == null || value.stream().noneMatch(parentIds::contains)) {
List<T> data = nodeParentData.get(key);
if (data == null) {
data = nodeData.get(key);
}
Optional.ofNullable(data).orElse(new ArrayList<>())
.forEach(item -> {
R instance = supplier.get();
instance.setNode(key);
instance.setData(item);
treeDTO.add(instance);
});
iterator.remove();
}
}
Stack<R> stack = new Stack<>();
stack.addAll(treeDTO);
while (!stack.isEmpty()) {
R pop = stack.pop();
iterator = node.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Set<String>> next = iterator.next();
Set<String> value = next.getValue();
String key = next.getKey();
if (value.contains(pop.getNode())) {
List<T> nodeParentDataValue = nodeParentData.getOrDefault(key + pop.getNode(), new ArrayList<>());
nodeParentDataValue.forEach(item -> {
R instance = supplier.get();
instance.setNode(key);
instance.setData(item);
stack.push(instance);
pop.addChild(instance);
});
value.remove(pop.getNode());
if (value.isEmpty()) {
iterator.remove();
}
}
}
}
return treeDTO;
}
/**
* 获取新实例
*
* @param clazz 克拉兹
* @return {@link R}
*/
private static <T, R extends TreeInterface<T>> R getNewInstance(Class<R> clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
import lombok.*;
/**
* 用于获取数据树结构数据时使用的通用参数
*
* @param <T> 实际的数据对象类型
*/
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
@Setter
public class TreeParam<T> {
/**
* 数据主键
*/
private String key;
/**
* 数据上级主键
*/
private String parentKey;
/**
* 原始数据对象
*/
private T data;
}
import java.util.List;
public interface TreeInterface<T> {
String getNode();
void setNode(String node);
T getData();
void setData(T data);
<R extends TreeInterface<T>> R getParent();
void setParent(TreeInterface<T> parent);
<R extends TreeInterface<T>> List<R> getChildren();
/**
* 添加孩子
*
* @param child 孩子
*/
void addChild(TreeInterface<T> child);
/**
* 等级
*
* @return int
*/
default int level() {
if (getParent() == null) {
return 0;
} else {
return getParent().level() + 1;
}
}
}
import lombok.*;
import java.util.ArrayList;
import java.util.List;
/**
* 树默认值
*
* @author jm
* @date 2024/02/17
*/
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TreeDefault<T> implements TreeInterface<T> {
@Setter
private String node;
@Setter
private T data;
private TreeDefault<T> parent;
private List<TreeDefault<T>> children;
@Override
public void setParent(TreeInterface<T> parent) {
if (parent != null && TreeDefault.class.isAssignableFrom(parent.getClass())) {
this.parent = (TreeDefault<T>) parent;
}
}
@Override
public void addChild(TreeInterface<T> child) {
if (child != null && TreeDefault.class.isAssignableFrom(child.getClass())) {
TreeDefault<T> childDTO = (TreeDefault<T>) child;
if (children == null) {
children = new ArrayList<>();
}
child.setParent(this);
children.add(childDTO);
}
}
}