Java Stream流轻松遍历树形结构

发布时间:2023年12月28日

在日常开发中,经常会遇到返回树形及遍历树形结构的需求,比如构建菜单,项目-任务树形结构,角色权限树形结构等。数据库一般使用parent_id来表示上一层级,遍历的时候一般使用递归或多层for循环,增加了数据库的查询压力。

为了降低数据库的查询压力,我们可以使用Java8中的Stream流一次性把数据查出来,然后通过流式处理。

话不多说,直接上Demo。

首先,创建一个Menu 菜单的实体类


@Data
@Builder
public class Menu {
    /**
     * 唯一id
     */
    public Integer id;
    /**
     * 菜单名称
     */
    public String name;
    /**
     * 上级id ,根节点为0
     */
    public Integer parentId;
    /**
     * 子节点信息
     */
    public List<Menu> childList;

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

    public Menu(Integer id, String name, Integer parentId, List<Menu> childList) {
        this.id = id;
        this.name = name;
        this.parentId = parentId;
        this.childList = childList;
    }
}

接下来,模拟生成一颗树形结构List<Menu> 集合。

private static List<Menu> createTree() {
        //模拟创建一棵树
        return  = Arrays.asList(
                new Menu(1, "目录", 0),
                new Menu(2, "第一章节", 1),
                new Menu(3, "1.1 大战光明顶", 2),
                new Menu(4, "1.2 偶遇赵敏", 2),
                new Menu(5, "1.3 迎娶周芷若", 2),
                new Menu(6, "第二章节", 1),
                new Menu(7, "2.1 挥泪斩狮王", 6),
                new Menu(8, "2.2 大意失街亭", 6),
                new Menu(9, "2.2.1 败走麦城", 7),
                new Menu(10, "2.2.2 火烧赤壁", 7),
                new Menu(11, "第三章节", 1),
                new Menu(12, "3.1 刺杀董卓", 11),
                new Menu(13, "3.1.1 貂蝉献艺", 12),
                new Menu(14, "结束", 0)
        );
      
    }

然后,使用根据上级 parentId 获取所有子节点的方法,这里我们可以使用递归的方式去实现

private static List<Menu> getAllChildrenByRoot(Menu root, List<Menu> all) {
        return all.stream().filter(m -> Objects.equals(m.getParentId(), root.getId()))
                .peek(
                        (m) -> m.setChildList(getAllChildrenByRoot(m, all))
                ).collect(Collectors.toList());
    }

最后,使用main方法验证一下

public static void main(String[] args) {
        List<Menu> menus = createTree();

        List<Menu> menuList = menus.stream().filter(m -> m.getParentId() == 0)
                .peek(
                (m) -> m.setChildList(getAllChildrenByRoot(m, menus))
        ).collect(Collectors.toList());
        System.out.println("/*****collect to json*****/");
        System.out.println(JSONObject.toJSON(menuList));
    }

打印一下结果

[
    {
        "name":"目录",
        "childList":[
            {
                "name":"第一章节",
                "childList":[
                    {
                        "name":"1.1 大战光明顶",
                        "childList":[

                        ],
                        "id":3,
                        "parentId":2
                    },
                    {
                        "name":"1.2 偶遇赵敏",
                        "childList":[

                        ],
                        "id":4,
                        "parentId":2
                    },
                    {
                        "name":"1.3 迎娶周芷若",
                        "childList":[

                        ],
                        "id":5,
                        "parentId":2
                    }
                ],
                "id":2,
                "parentId":1
            },
            {
                "name":"第二章节",
                "childList":[
                    {
                        "name":"2.1 挥泪斩狮王",
                        "childList":[
                            {
                                "name":"2.2.1 败走麦城",
                                "childList":[

                                ],
                                "id":9,
                                "parentId":7
                            },
                            {
                                "name":"2.2.2 火烧赤壁",
                                "childList":[

                                ],
                                "id":10,
                                "parentId":7
                            }
                        ],
                        "id":7,
                        "parentId":6
                    },
                    {
                        "name":"2.2 大意失街亭",
                        "childList":[

                        ],
                        "id":8,
                        "parentId":6
                    }
                ],
                "id":6,
                "parentId":1
            },
            {
                "name":"第三章节",
                "childList":[
                    {
                        "name":"3.1 刺杀董卓",
                        "childList":[
                            {
                                "name":"3.1.1 貂蝉献艺",
                                "childList":[

                                ],
                                "id":13,
                                "parentId":12
                            }
                        ],
                        "id":12,
                        "parentId":11
                    }
                ],
                "id":11,
                "parentId":1
            }
        ],
        "id":1,
        "parentId":0
    },
    {
        "name":"结束",
        "childList":[

        ],
        "id":14,
        "parentId":0
    }
]

文章来源:https://blog.csdn.net/zuihongyan518/article/details/135277469
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。