package com.utils.lamdatree;
import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.*;
public class CreteaTree {
@Data
@Accessors(chain = true)
public static class Node {
Integer id;
Integer pid;
List<Node> children;
}
public static void main(String[] args) {
final List<Node> nodeList = createRandomTestTreeInfoList(2, 2, 2);
System.out.println(JSON.toJSONString(nodeList));
ListToTreeUtil.listToTree(nodeList, Node::getId, Node::getPid, Node::getChildren, Node::setChildren);
}
public static List<Node> createRandomTestTreeInfoList(int tierN, int rootN, int childN) {
final Random random = new Random();
final int tier = tierN == 0 ? 5 + random.nextInt(5) : tierN;
final List<Node> testTrees = new ArrayList<>();
Queue<Node> pre = new LinkedList<>();
final int rootNum = rootN == 0 ? 1 + random.nextInt(5) : rootN;
for (int i = 0; i < rootNum; i++) {
final Node testTree = new Node().setId(testTrees.size());
testTrees.add(testTree);
pre.add(testTree);
}
for (int i = 0; i < tier; i++) {
final int childNum = childN == 0 ? 3 + random.nextInt(3) : childN;
final int size = pre.size();
for (int j = 0; j < size; j++) {
final Integer pid = Objects.requireNonNull(pre.poll()).getId();
for (int k = 0; k < childNum; k++) {
final Node child = new Node().setId(testTrees.size()).setPid(pid);
testTrees.add(child);
pre.offer(child);
}
}
}
return testTrees;
}
}
package com.utils.lamdatree;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
@Slf4j
public class ListToTreeUtil {
public interface GetLambdaName extends Serializable {
String METHOD_NAME = "writeReplace";
default String getLambdaMethodName() {
final Class<? extends GetLambdaName> aClass = this.getClass();
String implMethodName = null;
try {
final Method method = aClass.getDeclaredMethod(METHOD_NAME);
method.setAccessible(true);
SerializedLambda lambda = (SerializedLambda) method.invoke(this);
implMethodName = lambda.getImplMethodName();
} catch (Exception e) {
e.printStackTrace();
}
return implMethodName;
}
}
@FunctionalInterface
public interface XKFunction<T, R> extends Function<T, R>, GetLambdaName {
}
@FunctionalInterface
public interface XKBiConsumer<T, R> extends BiConsumer<T, R>, GetLambdaName {
}
@FunctionalInterface
public interface XKPredicate<T> extends Predicate<T>, GetLambdaName {
}
private static <T> String getMethodName(GetLambdaName fun) {
if (fun != null) {
final String lambdaMethodName = fun.getLambdaMethodName();
System.out.println("lambdaMethodName = " + lambdaMethodName);
return lambdaMethodName;
}
return null;
}
public static <T> List<T> listToTree(List<T> source, XKPredicate<T> isRoot, XKFunction<T, ?> idFun
, XKFunction<T, ?> pidFun, XKFunction<T, List<T>> getChildFun, XKBiConsumer<T, List<T>> setChildFun) {
if (Objects.isNull(source) || Objects.isNull(idFun) || Objects.isNull(pidFun)
|| Objects.isNull(getChildFun) || Objects.isNull(setChildFun) || source.isEmpty()) {
log.info("参数不满足,直接返回空List");
return new ArrayList<>();
}
log.info("isRoot->{},idFun->{},pidFun->{},getChildFun->{},setChildFun->{}", getMethodName(isRoot)
, getMethodName(idFun), getMethodName(pidFun), getMethodName(getChildFun), getMethodName(setChildFun));
if (log.isDebugEnabled()) {
log.debug("source->{}", JSON.toJSONString(source));
}
final List<T> ret = new ArrayList<>();
final Map<Object,T> map = new HashMap<>();
source.forEach(t -> {
Optional.ofNullable(isRoot).map(r -> {
if (isRoot.test(t)) {
ret.add(t);
}
return r;
}).orElseGet(() -> {
Optional.ofNullable(pidFun.apply(t)).orElseGet(() -> {
ret.add(t);
return null;
});
return null;
});
map.put(idFun.apply(t), t);
});
source.forEach(t -> {
map.computeIfPresent(pidFun.apply(t), (k, v) -> {
Optional.ofNullable(getChildFun.apply(v)).orElseGet(() -> {
final List<T> list = new ArrayList<>();
setChildFun.accept(v, list);
return list;
}).add(t);
return v;
});
});
if (log.isDebugEnabled()) {
log.debug("返回数据->{}", JSON.toJSONString(ret));
}
System.out.println(JSON.toJSONString(ret));
return ret;
}
public static <T> List<T> listToTree(List<T> source, XKFunction<T, ?> idFun, XKFunction<T, ?> pidFun
, XKFunction<T, List<T>> getChildFun, XKBiConsumer<T, List<T>> setChildFun) {
return listToTree(source, null, idFun, pidFun, getChildFun, setChildFun);
}
}
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>