Stream分组掌握这个你代码可以少些一半了
Posted 沛沛老爹
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Stream分组掌握这个你代码可以少些一半了相关的知识,希望对你有一定的参考价值。
背景
查询的List列表中的某列的值,需要根据另外一个对象列表的List中的某个属性来统计。
例如现在存在A对象ClassA和B对象StudentB。
需要对查询出来的List<ClassA>列表中展示StudentB中的用户特长属性列表。用户特长信息存在与StudentAttrC中。
他们的关系如下
代码如下
@Data
public class ClassA
private Integer id;
//人数
private Integer count;
...
@Data
public class StudentB
private Integer id;
private Integer classAId;
private Integer amount;
...
@Data
public class StudentAttrC
private Integer id;
private Integer StudentBId;
private BigDecimal money;
...
现在需要在List<ClassA>中,需要将每个班的人数统计展示出来。
因为用到的是分布式系统和多库的开发模式,要求不能进行连表查询。
(先不考虑ClassAttr中的统计条件了,估计这会儿有的小伙伴们头有点大。。。。)
好吧,立马安排
解决思路
推荐使用Stream中的groupBy和sum来解决
可以看下下面的这个例子,统计列表中的所有指定性别的用户年纪之和。
package com.test;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Test
public static void main(String[] args)
List<TestA> list =initData();
Map<Integer,Integer> map =list.stream().collect(Collectors.groupingBy(TestA::getSex,Collectors.summingInt(TestA::getAge)));
for(Map.Entry<Integer,Integer> entry:map.entrySet())
System.out.println("sex:"+entry.getKey()+" ageSum:"+entry.getValue());
public static List<ClassA> initData()
List<TestA> list = new ArrayList<>();
for(int i=0;i<5;i++)
TestA a = new TestA();
a.setAge(i);
a.setSex(1);
a.setName("测试"+i);
list.add(a);
TestA b = new TestA();
BeanUtils.copyProperties(a,b);
b.setSex(2);
b.setAge(a.getAge()*2);
list.add(b);
return list;
@Data
class TestA
private Integer age;
private Integer sex;
private String name;
我们可以看到根据性别不同,
最后统计出来的结果为一个map,里面根据sex分组了两条不同的数据。
整个代码中,做统计只用了一行代码
Map<Integer,Integer> map =list.stream()
.collect(Collectors.groupingBy(TestA::getSex,
Collectors.summingInt(TestA::getAge)));
在这里面,我们使用了groupingBy来进行分组。
使用了summingInt来进行统计。
这样一行代码解决了我们的问题。同时还用到了map的特性。
优越性总结
开发效能
代码写的多,中间容易出差错。
同时写的多的话,后续维护也比较麻烦,特别是嵌套里面的逻辑比较傲娇的那种。
代码可读性
如果是常规的统计的话,我们需要将所有的数据拿出来,然后使用循环一行行的匹配。
这样可读性比较糙,使用map的方式一目了然。
代码性能
用for循环的话,走的是O(n)的方式。
用map,使用的是O(1)。所以是没有可比性的。
同时,如果你遇到那种假程序员,往里面嵌套读取数据库,那就是一场人间灾难了。
好了,根据上面的例子,你就可以尝试解决提出的那个问题了,再嵌套ClassAttrC也不在话下了。
以上是关于Stream分组掌握这个你代码可以少些一半了的主要内容,如果未能解决你的问题,请参考以下文章
JDK8对List进行分组操作(stream的groupby)