三级分类之Stream的使用

参考

简介

在跟着尚硅谷学习谷粒商城中遇到这个三级分类问题,使用了Stream Api,记录一下

过程

主要内容就是对商品类别表进行三级分类,category表设计如下,主要关注,分类id,父分类id,排序这几个字段

image

数据内容,这里只贴了30条,总1000条,随后在web上展示

image

了解了需求,CategoryEntity如下,关注新加入的非数据库字段属性List<CategoryEntity> children,用于存放该分类下的子分类

@Data
@TableName("pms_category")
public class CategoryEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 分类id
     */
    @TableId
    private Long catId;
    /**
     * 分类名称
     */
    private String name;
    /**
     * 父分类id
     */
    private Long parentCid;
    /**
     * 层级
     */
    private Integer catLevel;
    /**
     * 是否显示[0-不显示,1显示]
     */
    private Integer showStatus;
    /**
     * 排序
     */
    private Integer sort;
    /**
     * 图标地址
     */
    private String icon;
    /**
     * 计量单位
     */
    private String productUnit;
    /**
     * 商品数量
     */
    private Integer productCount;
    /**
     * 子分类
     */
    @TableField(exist = false)
    private List<CategoryEntity> children;

}

我们重点关注业务层,dao层使用的是Mybatis-Plus,不多介绍

就是在这里我们使用了Stream处理了从数据库查到的所有分类信息

处理过程:

  • 从数据库查到所有分类信息List<CategoryEntity>
  • 先查到所有的一级分类(parentCid为0的,从上面的数据内容也可看出来)
  • 接着从这些父分类,找到属于他的子分类(通过getChildren函数)
  • sorted根据sort字段升序排列
  • collect形成集合
@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    ...

    @Override
    public List<CategoryEntity> listWithTree() {
        // 1、查出所有分类
        List<CategoryEntity> entities = baseMapper.selectList(null);
        // 2、组装树形结构

        // 2.1、一级分类
        List<CategoryEntity> level1Menu = entities.stream().filter((categoryEntity) ->
                categoryEntity.getParentCid() == 0
        ).peek((menu) ->
                menu.setChildren(getChildren(menu, entities))
        ).sorted(
                Comparator.comparingInt(CategoryEntity::getSort)
        ).collect(Collectors.toList());
        return level1Menu;
    }

    /**
     * 递归查找所有菜单的子菜单
     * @param root
     * @param all
     * @return
     */
    private List<CategoryEntity> getChildren(CategoryEntity root, List<CategoryEntity> all) {
        List<CategoryEntity> children = all.stream().filter((categoryEntity ->
                categoryEntity.getParentCid().equals(root.getCatId()))
        ).peek((categoryEntity ->
                categoryEntity.setChildren(getChildren(categoryEntity, all)))
        ).sorted(
                Comparator.comparingInt(CategoryEntity::getSort)
        ).collect(Collectors.toList());
        return children;
    }
    
    ...
        
}

最后web显示如下,我使用的JSONView插件,也可以用F12查看相关信息

image-20210808171639929

结果就是我们期望的结果,观察发现排序也正确,“手机”排在首位

思考

如果这个业务不使用Stream该怎么做,会有多复杂,从这里就可体会到Stream的强大

使用Stream,需要哪些知识?

首先作为JDK1.8的重点升级,JDK1.8的lambda表达式、函数式接口、链式编程都是重点

四大函数式接口

这些都可以直接搜源码看接口怎样设计的就明白怎么用了,下面我用白话概括一下

Function 函数式接口

传入一个参数,由这个参数返回值

Predicate 断言型接口

传入一个参数,由这个参数进行判断,返回布尔值

Consumer 消费型接口

传入一个参数,由这个参数进行处理,无返回

Supplier 供给型接口

无参数,返回一个值

回想

在使用Stream其实就是传入一些函数式接口,再结合使用lambda表达式就变得非常简便

想想但是学的使用体会还没有这么大,直到遇见了真的业务,感受就马上不同了

总结

此后,我终于能体会到一些算法题的业务场景了,还有JavaSE基础真的很重要,更多的得慢慢感受了

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容