乐趣区

恕我直言你可能真的不会java第10篇集合元素归约

Stream API 为我们提供了 Stream.reduce 用来实现集合元素的归约。reduce 函数有三个参数:

  • Identity 标识:一个元素,它是归约操作的初始值,如果流为空,则为默认结果。
  • Accumulator 累加器:具有两个参数的函数:归约运算的部分结果和流的下一个元素。
  • Combiner 合并器(可选):当归约并行化时,或当累加器参数的类型与累加器实现的类型不匹配时,用于合并归约操作的部分结果的函数。


注意观察上面的图,我们先来理解累加器:

  • 阶段累加结果作为累加器的第一个参数
  • 集合遍历元素作为累加器的第二个参数

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 并行流计算的威力。

在进行并行流计算的时候,可能会将集合元素分成多个组计算。为了更快的将分组计算结果累加,可以使用合并器。

Integer total2 = employees
        .parallelStream()
        .map(Employee::getAge)
        .reduce(0,Integer::sum,Integer::sum);  // 注意这里 reduce 方法有三个参数

System.out.println(total); //346

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客。

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力!。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

  • 《手摸手教你学 Spring Boot2.0》
  • 《Spring Security-JWT-OAuth2 一本通》
  • 《实战前后端分离 RBAC 权限管理系统》
  • 《实战 SpringCloud 微服务从青铜到王者》
  • 《VUE 深入浅出系列》
退出移动版