大家好,又见面了,我是你们的朋友全栈君。
package com.ciih.workshop.utils; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import lombok.SneakyThrows; import java.lang.invoke.SerializedLambda; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.stream.Collectors; /** * 树形工具类-函数版 * * @author sunziwen */ public class TreeUtil { /** * Map版本(速度比递归要快很多) * listToTree * * @param target 需转换的数据 * @param getId 主键 * @param getParentId 父id (父id必须和主键相同类型) * @param getChildren 子集 * @param setChildren 子集 * @return tree */ public static <T, R> List<T> listToTree(List<T> target, Function<T, R> getId, Function<T, R> getParentId, Function<T, List<T>> getChildren, BiConsumer<T, List<T>> setChildren) { Map<R, T> oldMap = target.stream().collect(Collectors.toMap(getId, T -> T)); List<T> result = new ArrayList<>(); target.forEach(tree -> { T parent = oldMap.get(getParentId.apply(tree)); if (parent == null) { result.add(tree); } else { List<T> ch = getChildren.apply(parent); if (ch == null) { ch = new ArrayList<>(); } ch.add(tree); setChildren.accept(parent, ch); } }); return result; } /** * @param list 树结构的基础数据集 * @param getIdFn 获取主键的函数 * @param getParentIdFn 获取父节点的函数 * @param getChildrenFn 获取子集的函数 * @param <T> t * @param <R> r * @return t */ @SneakyThrows public static <T, R> List<T> treeOut(List<T> list, Function<T, R> getIdFn, Function<T, R> getParentIdFn, SFunction<T, R> getChildrenFn) { /*所有元素的Id*/ List<Object> ids = list.stream().map(getIdFn).collect(Collectors.toList()); /*查出所有顶级节点*/ List<T> topLevel = list.stream().filter(x -> { R apply = getParentIdFn.apply(x); return !ids.contains(apply); }).collect(Collectors.toList()); return TreeUtil.recursion(topLevel, list, getIdFn, getParentIdFn, getChildrenFn); } @SneakyThrows private static <T, R> List<T> recursion(List<T> superLevel, List<T> list, Function<T, R> getIdFn, Function<T, R> getParentIdFn, SFunction<T, R> getChildrenFn) { //获取setChildren的Method Method writeReplaceMethod = getChildrenFn.getClass().getDeclaredMethod("writeReplace"); boolean accessible = writeReplaceMethod.isAccessible(); writeReplaceMethod.setAccessible(true); SerializedLambda serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(getChildrenFn); writeReplaceMethod.setAccessible(accessible); String setMethodName = serializedLambda.getImplMethodName().replaceFirst("g", "s"); Method setMethod = Class.forName(serializedLambda.getImplClass().replace("/", ".")).getDeclaredMethod(setMethodName, List.class); for (T t : superLevel) { List<T> children = list.stream().filter(x -> { R apply = getParentIdFn.apply(x); R apply1 = getIdFn.apply(t); return apply.equals(apply1); }).collect(Collectors.toList()); if (children.size() <= 0) { continue; } List<T> recursion = recursion(children, list, getIdFn, getParentIdFn, getChildrenFn); setMethod.invoke(t, recursion); } return superLevel; } }
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/148050.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...