三级分类之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基础真的很重要,更多的得慢慢感受了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无奈何杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值