文章目录
前言
在今天的项目中,需要将商品分类信息封装成父子层级的数据结构
一、相关数据准备
1.分类父子层级示例展示
[
{
"index": 1,
"categoryChild": [
{
"categoryChild": [
{
"categoryName": "电子书",
"categoryId": 1
},
{
"categoryName": "网络原创",
"categoryId": 2
}
],
"categoryName": "电子书刊",
"categoryId": 1
}
],
"categoryName": "图书、音像、电子书刊",
"categoryId": 1
},
{
"index": 2,
"categoryChild": [
{
"categoryChild": [
{
"categoryName": "超薄电视",
"categoryId": 1
},
{
"categoryName": "全面屏电视",
"categoryId": 2
},
],
"categoryName": "电视",
"categoryId": 1
},
],
"categoryName": "家用电器",
"categoryId": 2
}
]
2.数据库相关展示
2.1涉及的表
这其中,base_category1中的id与base_category2的category1_id相关联,base_category2中的id与base_category3中的category2_id相关联,他们之间有一对多、多对一的关系
2.2 建立视图
我们可以建立一个视图(view),把三张表关联起来,视图id就是三级分类id,这样通过三级分类id就可以查询到相应数据,效果如下:
建立视图相关代码:
create view base_category_view2 as
select c3.id id,
c1.id category1_id, c1.name category1_name,
c2.id category2_id,c2.name category2_name,
c3.id category3_id,c3.name category3_name
from base_category1 c1
inner join base_category2 c2
on c1.id=c2.category1_id
inner join base_category3 c3
on c2.id=c3.category2_id
二、具体实现
//根据分类父子层级示例封装后台数据
public List<JSONObject> getBaseCategoryList() {
List<JSONObject> jsonObjectList = new ArrayList<>();
//获取首页分类集合 这一步,是利用mybatisplus先从刚刚创建的视图中
//查询到所有数据
List<BaseCategoryView> baseCategoryViews = baseCategoryViewMapper.selectList(null);
/**
* 首先按照一级分类进行分组
* 使用stream流的方式将集合根据category1_id分组成一个以category1_id为键,
* List<BaseCategoryView>为值的map集合
*/
Map<Long, List<BaseCategoryView>> category1Map = baseCategoryViews.stream().collect(Collectors.groupingBy(new Function<BaseCategoryView, Long>() {
@Override
public Long apply(BaseCategoryView baseCategoryView) {
return baseCategoryView.getCategory1Id();
}
}));
//设置一级分类的index 遍历一级分类分组以后的map集合
int index = 1;
for (Map.Entry<Long, List<BaseCategoryView>> category1KeyAndValue : category1Map.entrySet()) {
//这个jsonObject1对象必须每次循环都要new,如果放在循环外层,jsonObjectList
//中的所有值被最后一次jsonObject1所put的键值对所覆盖,jsonObject1 和 jsonObject1同理
JSONObject jsonObject1 = new JSONObject();
//设置一级分类信息
jsonObject1.put("index", index++);
jsonObject1.put("categoryName", category1KeyAndValue.getValue().get(0).getCategory1Name());
jsonObject1.put("categoryId", category1KeyAndValue.getValue().get(0).getCategory1Id());
/**
* 需要的二级分类子节点必须要等遍历完二级分类信息,因此先进行遍历二级分类信息
* 而二级分类想要设置三级分类子节点,就必须先遍历三级分类信息,又因为一级分类对应
* 多个二级分类,二级分类又对应多个三级分类,因此需要层层嵌套从里到外,有了三级分类
*遍历后的全部信息才能设置二级分类的三级分类子节点,之后再遍历完二级分类的全部信息才
* 能设置一级分类的二级分类子节点
*/
//遍历二级分类信息
List<JSONObject> jsonObjectList2 = new ArrayList<>();
Map<Long, List<BaseCategoryView>> category2Map = category1KeyAndValue.getValue().stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));
for (Map.Entry<Long, List<BaseCategoryView>> category2KeyAndValue : category2Map.entrySet()) {
JSONObject jsonObject2 = new JSONObject();
jsonObject2.put("categoryName", category2KeyAndValue.getValue().get(0).getCategory2Name());
jsonObject2.put("categoryId", category2KeyAndValue.getValue().get(0).getCategory2Id());
//遍历三级分类信息
List<JSONObject> jsonObjectList3 = new ArrayList<>();
Map<Long, List<BaseCategoryView>> category3Map = category2KeyAndValue.getValue().stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory3Id));
for (Map.Entry<Long, List<BaseCategoryView>> category3KeyAndValue : category3Map.entrySet()) {
JSONObject jsonObject3 = new JSONObject();
jsonObject3.put("categoryName", category3KeyAndValue.getValue().get(0).getCategory3Name());
jsonObject3.put("categoryId", category3KeyAndValue.getValue().get(0).getCategory3Id());
//将每组三级分类信息加入三级分类集合
jsonObjectList3.add(jsonObject3);
}
//设置二级分类的子节点信息(三级分类信息)
jsonObject2.put("categoryChild", jsonObjectList3);
//将每组二级分类信息加入二级分类集合
jsonObjectList2.add(jsonObject2);
}
//设置一级分类的子节点信息(二级分类信息)
jsonObject1.put("categoryChild", jsonObjectList2);
//收集全部一级分类信息
jsonObjectList.add(jsonObject1);
}
//返回包含完整的一、二、三级分类信息
return jsonObjectList;
}
三、 总结
1.java中的stream流
Stream流是一种函数式编程的概念,它可以用来处理集合或数组等数据源的元素.
1.1优点
1.Stream流提供了一种简洁的方式来处理集合中的元素,可以通过链式操作来实现复杂的数据处理逻辑,减少了代码的编写量
2.Stream流支持并行处理,可以自动将数据源分成多个部分并行处理,提高了处理大数据量的效率。
3.Stream流中的操作是延迟计算的,只有在终止操作时才会执行,这样可以根据需要灵活地选择执行哪些操作,提高了程序的性能。
4.Stream流鼓励使用函数式编程的思想,可以通过Lambda表达式来定义操作,使代码更加简洁、易读。
1.2缺点
1.可读性:虽然Stream流可以使代码更加简洁,但有时候也可能会降低代码的可读性,特别是对于复杂的操作逻辑,可能需要花费更多的时间来理解代码。
2.不可变性:Stream流中的操作是基于不可变对象的,每次操作都会返回一个新的Stream流,这可能会导致频繁的对象创建和销毁,对于大数据量的处理可能会带来一定的性能开销。
3.性能问题:虽然Stream流支持并行处理,但并不是所有的场景都适合并行处理,有时候并行处理反而会降低性能,需要根据具体情况进行评估和优化。
2.mysql中的视图
MySQL中的视图(View)是一种虚拟表,它是基于一个或多个表的查询结果集,并且可以像表一样被查询和使用。
2.1 优点
1.它可以简化复杂查询,将复杂的查询逻辑封装在一个视图中,使得查询变得简单明了,减少了重复编写复杂查询的工作量。
2.通过视图,还可以限制用户只能访问他们需要的数据,可以对视图进行权限控制,提高了数据的安全性。
3.视图可以隐藏底层表的结构和细节,将数据的逻辑关系抽象出来,提供更高层次的数据抽象,简化了数据操作。
4.通过视图,可以将对底层表的复杂数据修改操作简化为对视图的修改操作,减少了数据操作的复杂性。
2.2缺点
1.性能问题:视图在查询时需要实时计算,可能会引入一定的性能开销,特别是当视图基于复杂查询或多个表时,可能会导致查询变慢。
2.存储空间占用:视图本身并不存储数据,但是会占用一定的存储空间,特别是当视图基于大量数据或复杂查询时,可能会占用较大的存储空间。
3.更新限制:视图一般是只读的,对于基于多个表的视图,可能无法直接进行更新操作,需要对底层表进行更新。
4.版本控制问题:当底层表结构发生变化时,可能会导致视图无法正常使用,需要及时更新视图以适应底层表的变化。