首页 > 解决方案 > Java 8 - reduce(0, Integer::sum) 和 reduce(0, (a, b) -> a+b) 之间的区别

问题描述

我是新手Java 8,确实找到了一些方法additionmultiply并且subtraction。我将发布仅用于添加的问题。

我写了下面的代码并在 Sum1 和 Sum2 中收集输出。两种方法都reduce(0, Integer::sum)给出.reduce(0, (a, b) -> a+b);了相同的结果。明智地使用性能的最佳方法是什么,如果使用大整数值,为什么?

List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);

Integer sum1 = numbers.stream().reduce(0, (a, b) -> a+b);
System.out.println("SUM ="+sum1);

Integer product = numbers.stream().reduce(0, (a, b) -> a*b);
System.out.println("PRODUCT = "+product);

int sum2 = numbers.stream().reduce(0, Integer::sum);
System.out.println("SUM 2= "+sum2);

Optional<Integer> sum3 = numbers.stream().reduce((a, b) -> (a + b));
System.out.println("SUM3="+sum3);

// Updated as per  @Hadi J comment
int sum4 = numbers.stream().mapToInt(Integer::intValue).sum();
System.out.println("Sum ="+sum4);

标签: javacollectionsjava-8java-streamreduce

解决方案


明智地使用性能的最佳方法是什么,如果使用大整数值,为什么?

主要思想是在处理基元及其对象表示时忽略自动装箱/拆箱。

添加两个Integer对象比添加两个int基元要复杂得多。您可以在这篇文章中找到更多详细信息。

所以最好的情况是当你有一个原始数组int[]并将它的元素相加到一个类型的累加器中int。因此这里不涉及拳击。

更糟糕(但不是最糟糕)的情况是当你将一个对象Integer与一个原语求和时int。它将导致第一个参数的拆箱。当您的初始数组或集合包含对象(例如 Integer[]、List 等...)并且累加器是原始的时,这就是它的工作方式。这将导致您的集合中的每个元素仅拆箱一次,而累加器将保持不变。

最坏的情况是将一组对象汇总到一个Integer累加器中。

  1. 普通的旧 Java:

    • 总结Integer[]Integer

      Integer[] array = {0,1,2,3,4,5,6,7,8,9};
      Integer sum = 0;
      // Each element of the array will be unboxed exactly once
      // sum will be unboxed 10 times
      // result of the sum will be boxed 10 times
      for(int i : array) sum += i;
      
    • 总结Integer[]int

      Integer[] array = {0,1,2,3,4,5,6,7,8,9};
      int sum = 0;
      // Each element of the array will be unboxed exactly once
      // result of the sum will be boxed 10 times
      for(int i : array) sum += i;
      
    • 总结int[]int

      int[] array = {0,1,2,3,4,5,6,7,8,9};
      int sum = 0;
      // No boxing/unboxing at all
      for(int i : array) sum += i;
      
  2. 流 API

    • 减少总和Stream<Integer>

      Stream<Integer> stream = Stream.of(0,1,2,3,4,5,6,7,8,9);
      // Each element will be unboxed exactly once
      // The accumulator will be unboxed 10 times
      // The result of the sum operation will be boxed 10 times
      Integer sum = stream.reduce(0, Integer::sum);
      
    • 减少Stream<Integer>映射到基元的总和int

      Stream<Integer> stream = Stream.of(0,1,2,3,4,5,6,7,8,9);
      // Each element will be unboxed exactly once
      // Neither accumulator not result will be unboxed/boxed
      int sum = stream.mapToInt(Integer::intValue).reduce(0, Integer::sum);
      
    • 减少总和IntStream

      IntStream stream = IntStream.of(0,1,2,3,4,5,6,7,8,9);
      // No boxing/unboxing at all
      int sum = stream.reduce(0, Integer::sum);
      // same as
      int sum2 = stream.sum();
      

推荐阅读