![](https://cdn.zimug.com/wx-zimug.png)
Stream API为我们提供了`Stream.reduce`用来实现集合元素的归约。reduce函数有三个参数:
* *Identity标识*:一个元素,它是归约操作的初始值,如果流为空,则为默认结果。
* *Accumulator累加器*:具有两个参数的函数:归约运算的部分结果和流的下一个元素。
* *Combiner合并器(可选)*:当归约并行化时,或当累加器参数的类型与累加器实现的类型不匹配时,用于合并归约操作的部分结果的函数。
![](https://img.kancloud.cn/bd/76/bd76776778618850781059c2ea5a5c8b_889x538.png)
注意观察上面的图,我们先来理解累加器:
* 阶段累加结果作为累加器的第一个参数
* 集合遍历元素作为累加器的第二个参数
## Integer类型归约
reduce初始值为0,累加器可以是lambda表达式,也可以是方法引用。
~~~
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
int result = numbers
.stream()
.reduce(0, (subtotal, element) -> subtotal + element);
System.out.println(result); //21
int result = numbers
.stream()
.reduce(0, Integer::sum);
System.out.println(result); //21
~~~
## String类型归约
不仅可以归约Integer类型,只要累加器参数类型能够匹配,可以对任何类型的集合进行归约计算。
~~~
List<String> letters = Arrays.asList("a", "b", "c", "d", "e");
String result = letters
.stream()
.reduce("", (partialString, element) -> partialString + element);
System.out.println(result); //abcde
String result = letters
.stream()
.reduce("", String::concat);
System.out.println(result); //ancde
~~~
## 复杂对象归约
计算所有的员工的年龄总和。
~~~
Employee e1 = new Employee(1,23,"M","Rick","Beethovan");
Employee e2 = new Employee(2,13,"F","Martina","Hengis");
Employee e3 = new Employee(3,43,"M","Ricky","Martin");
Employee e4 = new Employee(4,26,"M","Jon","Lowman");
Employee e5 = new Employee(5,19,"F","Cristine","Maria");
Employee e6 = new Employee(6,15,"M","David","Feezor");
Employee e7 = new Employee(7,68,"F","Melissa","Roy");
Employee e8 = new Employee(8,79,"M","Alex","Gussin");
Employee e9 = new Employee(9,15,"F","Neetu","Singh");
Employee e10 = new Employee(10,45,"M","Naveen","Jain");
List<Employee> employees = Arrays.asList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
Integer total = employees.stream().map(Employee::getAge).reduce(0,Integer::sum);
System.out.println(total); //346
~~~
* 先用map将Stream流中的元素由Employee类型处理为Integer类型(age)。
* 然后对Stream流中的Integer类型进行归约
## Combiner合并器的使用
除了使用map函数实现类型转换后的集合归约,我们还可以用Combiner合并器来实现,这里第一次使用到了Combiner合并器。
因为Stream流中的元素是Employee,累加器的返回值是Integer,所以二者的类型不匹配。这种情况下可以使用Combiner合并器对累加器的结果进行二次归约,相当于做了类型转换。
~~~
Integer total3 = employees.stream()
.reduce(0,(totalAge,emp) -> totalAge + emp.getAge(),Integer::sum); //注意这里reduce方法有三个参数
System.out.println(total); //346
~~~
计算结果和使用map进行数据类型转换的方式是一样的。
## 并行流数据归约(使用合并器)
对于大数据量的集合元素归约计算,更能体现出Stream并行流计算的威力。
![](https://img.kancloud.cn/77/5d/775d65715a631fe8d39a2861c0a3c94c_1017x563.png)
在进行并行流计算的时候,可能会将集合元素分成多个组计算。为了更快的将分组计算结果累加,可以使用合并器。
~~~
Integer total2 = employees
.parallelStream()
.map(Employee::getAge)
.reduce(0,Integer::sum,Integer::sum); //注意这里reduce方法有三个参数
System.out.println(total); //346
~~~
- 前言
- 1.lambda表达式会用了么
- 2.初识Stream-API
- 3.Stream的filter与谓语逻辑
- 4.Stream管道流的map操作
- 5.Stream的状态与并行操作
- 6.Stream性能差?不要人云亦云
- 7.像使用SQL一样排序集合
- 8.函数式接口Comparator
- 9.Stream查找与匹配元素
- 10.Stream集合元素归约
- 11.StreamAPI终端操作
- 12.java8如何排序Map
- Stream流逐行文件处理
- java8-forEach(持续发布中)
- 笔者其它作品推荐
- vue深入浅出系列
- 手摸手教你学Spring Boot2.0
- Spring Security-JWT-OAuth2一本通
- 实战前后端分离RBAC权限管理系统
- 实战SpringCloud微服务从青铜到王者