参考
简介
在跟着尚硅谷学习谷粒商城中遇到这个三级分类问题,使用了Stream Api,记录一下
过程
主要内容就是对商品类别表进行三级分类,category表设计如下,主要关注,分类id,父分类id,排序这几个字段
数据内容,这里只贴了30条,总1000条,随后在web上展示
了解了需求,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查看相关信息
结果就是我们期望的结果,观察发现排序也正确,“手机”排在首位
思考
如果这个业务不使用Stream该怎么做,会有多复杂,从这里就可体会到Stream的强大
使用Stream,需要哪些知识?
首先作为JDK1.8的重点升级,JDK1.8的lambda表达式、函数式接口、链式编程都是重点
四大函数式接口
这些都可以直接搜源码看接口怎样设计的就明白怎么用了,下面我用白话概括一下
Function 函数式接口
传入一个参数,由这个参数返回值
Predicate 断言型接口
传入一个参数,由这个参数进行判断,返回布尔值
Consumer 消费型接口
传入一个参数,由这个参数进行处理,无返回
Supplier 供给型接口
无参数,返回一个值
回想
在使用Stream其实就是传入一些函数式接口,再结合使用lambda表达式就变得非常简便
想想但是学的使用体会还没有这么大,直到遇见了真的业务,感受就马上不同了
总结
此后,我终于能体会到一些算法题的业务场景了,还有JavaSE基础真的很重要,更多的得慢慢感受了