树工具类记录

墨韵云阁
2025-07-01
点 赞
0
热 度
4
评 论
0

zhi_yue 文章摘要

墨韵云阁-GPT

/**
 * 树
 *
 * @author luoyuanxiang
 */
public class TreeUtil {

    /**
     * 将list合成树
     *
     * @param list           需要合成树的List
     * @param rootCheck      判断E中为根节点的条件,如:x->x.getPId()==-1L , x->x.getParentId()==null,x->x.getParentMenuId()==0
     * @param parentCheck    判断E中为父节点条件,如:(x,y)->x.getId().equals(y.getPId())
     * @param setSubChildren E中设置下级数据方法,如: Menu::setSubMenus
     * @param <E>            泛型实体对象
     * @return 合成好的树
     */
    public static <E> List<E> makeTree(List<E> list, Predicate<E> rootCheck, BiFunction<E, E, Boolean> parentCheck, BiConsumer<E, List<E>> setSubChildren) {
        return list.stream().filter(rootCheck).peek(x -> setSubChildren.accept(x, makeChildren(x, list, parentCheck, setSubChildren))).collect(Collectors.toList());
    }


    /**
     * 将树打平成tree
     *
     * @param tree           需要打平的树
     * @param getSubChildren 设置下级数据方法,如: Menu::getSubMenus,x->x.setSubMenus(null)
     * @param setSubChildren 将下级数据置空方法,如: x->x.setSubMenus(null)
     * @param <E>            泛型实体对象
     * @return 打平后的数据
     */
    public static <E> List<E> flat(List<E> tree, Function<E, List<E>> getSubChildren, Consumer<E> setSubChildren) {
        List<E> res = new ArrayList<>();
        forPostOrder(tree, item -> {
            setSubChildren.accept(item);
            res.add(item);
        }, getSubChildren);
        return res;
    }


    /**
     * 前序遍历
     *
     * @param tree           需要遍历的树
     * @param consumer       遍历后对单个元素的处理方法,如:x-> System.out.println(x)、 System.out::println打印元素
     * @param setSubChildren 设置下级数据方法,如: Menu::getSubMenus,x->x.setSubMenus(null)
     * @param <E>            泛型实体对象
     */
    public static <E> void forPreOrder(List<E> tree, Consumer<E> consumer, Function<E, List<E>> setSubChildren) {
        for (E l : tree) {
            consumer.accept(l);
            List<E> es = setSubChildren.apply(l);
            if (es != null && !es.isEmpty()) {
                forPreOrder(es, consumer, setSubChildren);
            }
        }
    }


    /**
     * 层序遍历
     *
     * @param tree           需要遍历的树
     * @param consumer       遍历后对单个元素的处理方法,如:x-> System.out.println(x)、 System.out::println打印元素
     * @param setSubChildren 设置下级数据方法,如: Menu::getSubMenus,x->x.setSubMenus(null)
     * @param <E>            泛型实体对象
     */
    public static <E> void forLevelOrder(List<E> tree, Consumer<E> consumer, Function<E, List<E>> setSubChildren) {
        Queue<E> queue = new LinkedList<>(tree);
        while (!queue.isEmpty()) {
            E item = queue.poll();
            consumer.accept(item);
            List<E> childList = setSubChildren.apply(item);
            if (childList != null && !childList.isEmpty()) {
                queue.addAll(childList);
            }
        }
    }


    /**
     * 后序遍历
     *
     * @param tree           需要遍历的树
     * @param consumer       遍历后对单个元素的处理方法,如:x-> System.out.println(x)、 System.out::println打印元素
     * @param setSubChildren 设置下级数据方法,如: Menu::getSubMenus,x->x.setSubMenus(null)
     * @param <E>            泛型实体对象
     */
    public static <E> void forPostOrder(List<E> tree, Consumer<E> consumer, Function<E, List<E>> setSubChildren) {
        for (E item : tree) {
            List<E> childList = setSubChildren.apply(item);
            if (childList != null && !childList.isEmpty()) {
                forPostOrder(childList, consumer, setSubChildren);
            }
            consumer.accept(item);
        }
    }

    /**
     * 对树所有子节点按comparator排序
     *
     * @param tree        需要排序的树
     * @param comparator  排序规则Comparator,如:Comparator.comparing(MenuVo::getRank)按Rank正序 ,(x,y)->y.getRank().compareTo(x.getRank()),按Rank倒序
     * @param getChildren 获取下级数据方法,如:MenuVo::getSubMenus
     * @param <E>         泛型实体对象
     * @return 排序好的树
     */
    public static <E> List<E> sort(List<E> tree, Comparator<? super E> comparator, Function<E, List<E>> getChildren) {
        for (E item : tree) {
            List<E> childList = getChildren.apply(item);
            if (childList != null && !childList.isEmpty()) {
                sort(childList, comparator, getChildren);
            }
        }
        tree.sort(comparator);
        return tree;
    }

    private static <E> List<E> makeChildren(E parent, List<E> allData, BiFunction<E, E, Boolean> parentCheck, BiConsumer<E, List<E>> children) {
        return allData.stream().filter(x -> parentCheck.apply(parent, x)).peek(x -> children.accept(x, makeChildren(x, allData, parentCheck, children))).collect(Collectors.toList());
    }


    // 用例

    public static void main(String[] args) {
        // 树构件
        List<MenuVO> menuVOList = new ArrayList<>();

        menuVOList.add(new MenuVO("1", "0", "菜单1"));
        menuVOList.add(new MenuVO("2", "1", "菜单2"));
        menuVOList.add(new MenuVO("3", "1", "菜单3"));
        menuVOList.add(new MenuVO("4", "2", "菜单4"));
        menuVOList.add(new MenuVO("5", "2", "菜单5"));
        menuVOList.add(new MenuVO("6", "3", "菜单6"));
        menuVOList.add(new MenuVO("7", "3", "菜单7"));
        menuVOList.add(new MenuVO("8", "4", "菜单8"));
        menuVOList.add(new MenuVO("9", "5", "菜单9"));
        menuVOList.add(new MenuVO("10", "0", "菜单10"));

        List<MenuVO> tree = TreeUtil.makeTree(menuVOList, x -> "0".equals(x.getParentId()), (x, y) -> x.getId().equals(y.getParentId()), MenuVO::setSubMenus);

        System.out.println(tree);

        System.out.println(TreeUtil.flat(tree, MenuVO::getSubMenus, x -> x.setSubMenus(null)));

        System.out.println(TreeUtil.sort(tree, Comparator.comparing(MenuVO::getName), MenuVO::getSubMenus));

        TreeUtil.forPreOrder(tree, System.out::println, MenuVO::getSubMenus);

        TreeUtil.forLevelOrder(tree, System.out::println, MenuVO::getSubMenus);

        TreeUtil.forPostOrder(tree, System.out::println, MenuVO::getSubMenus);
    }

    public static class MenuVO {

        private String id;
        private String parentId;
        private String name;
        private List<MenuVO> subMenus;

        public MenuVO(String id, String parentId, String name) {
            this.id = id;
            this.parentId = parentId;
            this.name = name;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getParentId() {
            return parentId;
        }

        public void setParentId(String parentId) {
            this.parentId = parentId;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public List<MenuVO> getSubMenus() {
            return subMenus;
        }

        public void setSubMenus(List<MenuVO> subMenus) {
            this.subMenus = subMenus;
        }

        @Override
        public String toString() {
            return "MenuVO{" +
                    "id='" + id + '\'' +
                    ", parentId='" + parentId + '\'' +
                    ", name='" + name + '\'' +
                    ", subMenus=" + subMenus +
                    '}';
        }
    }

}


乾坤未定,你我皆是牛马

墨韵云阁

infj 提倡者

站长

不具版权性
不具时效性

文章内容不具时效性。若文章内容有错误之处,请您批评指正。


目录

欢迎来到墨韵云阁的站点,为您导航全站动态

11 文章数
2 分类数
2 评论数
8标签数
最近评论
墨韵云阁

墨韵云阁


评论测试

墨韵云阁

墨韵云阁


感谢!

访问统计