一止长渊

Stream流建立多级菜单

N 人看过
字数:489字 | 预计阅读时长:2分钟

在数据库中我们常常遇到多级分类,我们如何简单便捷地建立一个多级分类树呢?

截屏2021-03-17 22.04.20.png
背景:数据库中有表描述商品分类信息,其中 parent_cid 就是其父类分类的 id,如何从数据库中查出结果后,找出每个分类的子分类。如果有 SQL 查询,如果想找到所有的二级分类,则需要先找到所有的一级分类的 id,然后利用 in 操作找出所有的二级分类,然后三级分类还是需要再写一个 SQL 语句,然后查询完还需要将相应的 children 归并到相应的一级分类中,这是十分麻烦的,多次 SQL 查询也会造成性能比较低。

利用 Stream 流中的 filter 先找出一级分类,然后对每个一级分类使用 map,对每个一级分类菜单又接着找出所有孩子这就是 getChildren,但是孩子菜单也有 children,所有 getChildren 是递归调用,递归的出口就是经过 filter 后的流已经没有数据了,就是该流中没了孩子了

    @Override
    public List<CategoryEntity> listWithTree() {
        // 查出所有分类
        List<CategoryEntity> entities = baseMapper.selectList(null);

        // 2.组装成父子的属性结构
        // 1)找到所有的以及分类
        List<CategoryEntity> level1Menus = entities.stream().filter(categoryEntity ->
            categoryEntity.getParentCid() == 0
        ).map((menu) ->{
            menu.setChildren(getChildren(menu, entities));
            return menu;
        }).sorted((x,y) -> x.getSort() - y.getSort()).collect(Collectors.toList());
        return level1Menus;
    }

    /**
     * 递归找出当前节点的所有孩子,递归出去条件就为filter找不到相应的孩子了
     * @param root
     * @param all
     * @return
     */
    private List<CategoryEntity> getChildren(CategoryEntity root, List<CategoryEntity> all){
        List<CategoryEntity> rootChildren = all.stream().filter(categoryEntity ->
            categoryEntity.getParentCid().equals(root.getCatId())
        ).map(categoryEntity -> {
            // 1、找到该子菜单的子菜单
            categoryEntity.setChildren(getChildren(categoryEntity, all));
            return categoryEntity;
        }).sorted((x,y) -> x.getSort() - y.getSort()).collect(Collectors.toList());
        return rootChildren;
    }

结果,找出了所有的菜单以及子菜单
截屏2021-03-17 22.20.10.png

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 (CC BY-NC-ND 4.0) 进行许可。