list集合转tree 树结构

package com.utils.lamdatree;

import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.experimental.Accessors;

import java.util.*;

/**
 * @author yy
 * @date 2022/7/31 16:09
 */
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;

/**
 * @author yy
 * @date 2022/7/31 15:31
 * 集合转树结构
 */
@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<>();
        }
//        if (log.isInfoEnabled()) {
        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);
    }
}

  <!--fastjson依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值