结合java 8函数式编程新特性,封装一个通用的TreeUtil。做树菜单可采用

这篇博客分享了一个Java工具类,用于构建树形数据结构并支持升序和降序排序。通过提供的函数式接口,可以灵活地处理不同类型的节点数据,适用于各种需要构建树形结构的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

直接上代码。有需要的朋友可以直接拿到项目中使用,非常方便。

首先看调用demo


/**
 * @ClassName TreeUtilDemo
 * @Author yangruilong
 * @Date 2021/8/19 17:47
 * @Version 1.0
 */
public class TreeUtilDemo {

    public static void main(String[] args) {

        // 包含所有的节点数据
        List<TreeVo> treeVos = new ArrayList<>();

        // 这个表示,你的结果集中,为顶级节点,parentId字段的值,如果为null就传null,如果为0就传0,可以随意赋值
        Long rootParentId = null;

        // 构建树
        List<TreeVo> treeVos1 =
            TreeUtil.buildTree(treeVos, TreeVo::getParentId, TreeVo::getId, TreeVo::setChildren, rootParentId);

        // 构建一个升序的树
        treeVos1 = TreeUtil.buildAscTree(treeVos, TreeVo::getParentId, TreeVo::getId, TreeVo::setChildren, rootParentId,
            TreeVo::getSort);

        // 构建一个降序的树
        treeVos1 = TreeUtil.buildDescTree(treeVos, TreeVo::getParentId, TreeVo::getId, TreeVo::setChildren,
            rootParentId, TreeVo::getSort);
      
    }

    @Data
    class TreeVo {

        private Long id;

        private Long parentId;

        private List<TreeVo> children;

        private Integer sort;

        private String nodeName;
    }
}

然后上工具栏代码


import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @ClassName TreeUtil
 * @Author yangruilong
 * @Date 2021/8/18 16:22
 * @Version 1.0
 */
public class TreeUtil {

    
    /***
     * 构建树
     *
     * @param listData
     *            需要构建的结果集
     * @param parentKeyFunction
     *            获取父主键的函数
     * @param keyFunction
     *            获取主键的函数
     * @param setChildrenFunction
     *            设置子集的函数
     * @param rootParentValue
     *            标识为父节点的值
     * @return java.util.List<T>
     * @author yangruilong
     */
    public static <T, U extends Comparable> List<T> buildTree(List<T> listData, Function<T, U> parentKeyFunction,
        Function<T, ? extends Comparable> keyFunction, BiConsumer<T, List<T>> setChildrenFunction, U rootParentValue) {
        return buildTree(listData, parentKeyFunction, keyFunction, setChildrenFunction, rootParentValue, null, null);
    }

    /***
     * 构建树,并且对结果集做升序处理
     * 
     * @Version 1.0
     * @param listData
     *            需要构建的结构集
     * @param parentKeyFunction
     *            获取父主键的函数
     * @param keyFunction
     *            获取主键的函数
     * @param setChildrenFunction
     *            设置子集的函数
     * @param rootParentValue
     *            标识为父节点的值
     * @param sortFunction
     *            获取排序字段的值
     * @return java.util.List<T>
     * @author yangruilong
     */
    public static <T, U extends Comparable> List<T> buildAscTree(List<T> listData, Function<T, U> parentKeyFunction,
        Function<T, ? extends Comparable> keyFunction, BiConsumer<T, List<T>> setChildrenFunction, U rootParentValue,
        Function<T, ? extends Comparable> sortFunction) {
        List<T> resultList =
            buildTree(listData, parentKeyFunction, keyFunction, setChildrenFunction, rootParentValue, sortFunction, 0);

        return sortList(resultList, sortFunction, 0);
    }

    /***
     * 构建树,并且对结果集做降序处理
     * 
     * @Version 1.0
     * @param listData
     *            需要构建的结构集
     * @param parentKeyFunction
     *            获取父主键的函数
     * @param keyFunction
     *            获取主键的函数
     * @param setChildrenFunction
     *            设置子集的函数
     * @param rootParentValue
     *            标识为父节点的值
     * @param sortFunction
     *            获取排序字段的值
     * @return java.util.List<T>
     * @author yangruilong
     */
    public static <T, U extends Comparable> List<T> buildDescTree(List<T> listData, Function<T, U> parentKeyFunction,
        Function<T, ? extends Comparable> keyFunction, BiConsumer<T, List<T>> setChildrenFunction, U rootParentValue,
        Function<T, ? extends Comparable> sortFunction) {
        List<T> resultList =
            buildTree(listData, parentKeyFunction, keyFunction, setChildrenFunction, rootParentValue, sortFunction, 1);

        return sortList(resultList, sortFunction, 1);
    }

    private static <T, U extends Comparable> List<T> buildTree(List<T> listData, Function<T, U> parentKeyFunction,
        Function<T, ? extends Comparable> keyFunction, BiConsumer<T, List<T>> setChildrenFunction, U rootParentValue,
        Function<T, ? extends Comparable> sortFunction, Integer sortedFlag) {
        // 筛选出根节点
        Map<Comparable, T> rootKeyMap = new HashMap<>();
        // 所有的节点
        Map<Comparable, T> allKeyMap = new HashMap<>();
        // 存id:List<ChildrenId>
        Map<Comparable, List<Comparable>> keyParentKeyMap = new HashMap<>();

        for (T t : listData) {
            Comparable key = keyFunction.apply(t);
            Comparable parentKey = parentKeyFunction.apply(t);
            // 如果根节点标识为null,值也为null,表示为根节点
            if (rootParentValue == null && parentKeyFunction.apply(t) == null) {
                rootKeyMap.put(key, t);
            }
            // 根节点标识有值,值相同表示为根节点
            if (rootParentValue != null && parentKeyFunction.apply(t).compareTo(rootParentValue) == 0) {
                rootKeyMap.put(key, t);
            }
            allKeyMap.put(key, t);
            if (parentKey != null) {
                List<Comparable> children = keyParentKeyMap.getOrDefault(parentKey, new ArrayList<>());
                children.add(key);
                keyParentKeyMap.put(parentKey, children);
            }
        }
        List<T> returnList = new ArrayList<>();
        // 封装根节点数据
        for (Comparable comparable : rootKeyMap.keySet()) {
            setChildren(comparable, returnList, allKeyMap, keyParentKeyMap, setChildrenFunction, sortFunction,
                sortedFlag);
        }

        return returnList;
    }

    private static <T> void setChildren(Comparable comparable, List<T> childrenList, Map<Comparable, T> childrenKeyMap,
        Map<Comparable, List<Comparable>> keyParentKeyMap, BiConsumer<T, List<T>> setChildrenFunction,
        Function<T, ? extends Comparable> sortFunction, Integer sortedFlag) {
        T t = childrenKeyMap.get(comparable);
        if (keyParentKeyMap.containsKey(comparable)) {
            List<T> subChildrenList = new ArrayList<>();
            List<Comparable> childrenComparable = keyParentKeyMap.get(comparable);
            for (Comparable c : childrenComparable) {
                setChildren(c, subChildrenList, childrenKeyMap, keyParentKeyMap, setChildrenFunction, sortFunction,
                    sortedFlag);
            }
            subChildrenList = sortList(subChildrenList, sortFunction, sortedFlag);
            setChildrenFunction.accept(t, subChildrenList);

        }
        childrenList.add(t);

    }

    private static <T> List<T> sortList(List<T> list, Function<T, ? extends Comparable> sortFunction,
        Integer sortedFlag) {
        if (sortFunction != null) {
            if (sortedFlag == 1) {
                return (List<T>)list.stream().sorted(Comparator.comparing(sortFunction).reversed())
                    .collect(Collectors.toList());
            } else {
                return (List<T>)list.stream().sorted(Comparator.comparing(sortFunction)).collect(Collectors.toList());
            }
        }
        return list;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值