如何将整数列表与 java 流相加?
How to sum a list of integers with java streams?
我想对整数列表求和。它的工作原理如下,但语法感觉不对。代码可以优化吗?
Map<String, Integer> integers;
integers.values().stream().mapToInt(i -> i).sum();
来自docs
Reduction operations
A reduction operation (also called a fold) takes a sequence of input elements and combines them into a single summary result by repeated application of a combining operation, such as finding the sum or maximum of a set of numbers, or accumulating elements into a list. The streams classes have multiple forms of general reduction operations, called reduce() and collect(), as well as multiple specialized reduction forms such as sum(), max(), or count().
Of course, such operations can be readily implemented as simple sequential loops, as in:
int sum = 0;
for (int x : numbers) {
sum += x;
}
However, there are good reasons to prefer a reduce operation over a mutative accumulation such as the above. Not only is a reduction "more abstract" -- it operates on the stream as a whole rather than individual elements -- but a properly constructed reduce operation is inherently parallelizable, so long as the function(s) used to process the elements are associative and stateless. For example, given a stream of numbers for which we want to find the sum, we can write:
int sum = numbers.stream().reduce(0, (x,y) -> x+y);
or:
int sum = numbers.stream().reduce(0, Integer::sum);
These reduction operations can run safely in parallel with almost no modification:
int sum = numbers.parallelStream().reduce(0, Integer::sum);
因此,对于您要使用的地图:
integers.values().stream().mapToInt(i -> i).reduce(0, (x,y) -> x+y);
或者:
integers.values().stream().reduce(0, Integer::sum);
我建议还有 2 个选项:
integers.values().stream().mapToInt(Integer::intValue).sum();
integers.values().stream().collect(Collectors.summingInt(Integer::intValue));
第二个使用 Collectors.summingInt()
收集器,还有一个 summingLong()
收集器,您可以将其与 mapToLong
一起使用。
第三个选项:Java 8 引入了一个非常有效的 LongAdder
累加器,旨在加速并行流和多线程环境中的汇总。在这里,这是一个使用示例:
LongAdder a = new LongAdder();
map.values().parallelStream().forEach(a::add);
sum = a.intValue();
这会起作用,但是 i -> i
正在执行一些自动拆箱,这就是它“感觉”奇怪的原因。 mapToInt
将流转换为 IntStream
“原始 int 值元素”。以下任一项都可以工作,并且可以更好地解释编译器使用您的原始语法在幕后做了什么:
integers.values().stream().mapToInt(i -> i.intValue()).sum();
integers.values().stream().mapToInt(Integer::intValue).sum();
你可以使用reduce方法:
long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, (x, y) -> x + y);
或
long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, Integer::sum);
您可以使用 collect 方法添加整数列表。
List<Integer> list = Arrays.asList(2, 4, 5, 6);
int sum = list.stream().collect(Collectors.summingInt(Integer::intValue));
您可以使用 reduce()
对整数列表求和。
int sum = integers.values().stream().reduce(0, Integer::sum);
这将是总结 int
类型数组的最短方法(对于 long
数组 LongStream
,对于 double
数组 DoubleStream
等等).不过,并非所有原始整数或浮点类型都具有 Stream
实现。
IntStream.of(integers).sum();
我已经声明了一个整数列表。
ArrayList<Integer> numberList = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));
您可以尝试使用以下这些不同的方式。
使用mapToInt
int sum = numberList.stream().mapToInt(Integer::intValue).sum();
使用summarizingInt
int sum = numberList.stream().collect(Collectors.summarizingInt(Integer::intValue)).getSum();
使用reduce
int sum = numberList.stream().reduce(Integer::sum).get().intValue();
希望对清单上有对象的人有所帮助。
如果您有一个对象列表并想对该对象的特定字段求和,请使用下面的方法。
List<ResultSom> somList = MyUtil.getResultSom();
BigDecimal result= somList.stream().map(ResultSom::getNetto).reduce(
BigDecimal.ZERO, BigDecimal::add);
不幸的是,流 API 看起来只有 returns 个来自 List<Integer>#stream()
的普通流。我猜他们是因为泛型的工作原理而被迫这样做。
这些普通的流是通用对象,所以没有像 sum()
等专门的方法,所以你必须默认使用奇怪的 re-stream “看起来像一个无操作”转换来获得对于那些方法... .mapToInt(i -> i)
.
另一个选项是使用“Eclipse Collections”,它类似于扩展的 java 流 API
IntLists.immutable.ofAll(integers.values()).sum();
List < Integer > listOfIntegers = List.of(1, 2, 10, 3, 4, 8, 5, 9, 6, 7);
Optional < Integer > maxValue = listOfIntegers
.stream().reduce((partialResult, currentValue) -> Math.max(partialResult, currentValue));
System.out.println("Maximum value : " + maxValue);
输出:最大值:可选[10]
这里还有一个没有人考虑的选项,它反映了 multi-core 环境的使用情况。如果你想利用它的优势,那么应该使用下一个代码而不是其他提到的解决方案:
int sum = integers.values().parallelStream().mapToInt(Integer::intValue)
.reduce(0, Integer::sum, Integer::sum);
这个方案和其他方案类似,但是请注意reduce中的第三个参数。它告诉编译器如何处理不同线程在流的不同块中计算的部分摘要。此外,使用 parallelStream()
而不是 stream()
。在这种情况下,它只会总结它。作为第三个参数的另一个选项是 (i, j) -> i + j
,这意味着它会将流块的值 (j
) 添加到当前值 (i
) 并将其用作下一个流块的当前值,直到处理完所有部分结果。
即使在使用普通 stream()
时,告诉减少如何处理流块的摘要也是有用的,以防万一有人或您将来想并行化它。最初的开发是最好的时机,因为稍后您需要记住它应该是什么,并且需要花一些时间再次理解该代码的用途。
当然,您可以使用不同的 lambda 方言来代替方法引用运算符。我更喜欢这种方式,因为它更紧凑,而且仍然易于阅读。
另请记住,这也可用于更复杂的计算,但请始终注意,无法保证流元素到线程的顺序和部署。
我想对整数列表求和。它的工作原理如下,但语法感觉不对。代码可以优化吗?
Map<String, Integer> integers;
integers.values().stream().mapToInt(i -> i).sum();
来自docs
Reduction operations A reduction operation (also called a fold) takes a sequence of input elements and combines them into a single summary result by repeated application of a combining operation, such as finding the sum or maximum of a set of numbers, or accumulating elements into a list. The streams classes have multiple forms of general reduction operations, called reduce() and collect(), as well as multiple specialized reduction forms such as sum(), max(), or count().
Of course, such operations can be readily implemented as simple sequential loops, as in:
int sum = 0; for (int x : numbers) { sum += x; }
However, there are good reasons to prefer a reduce operation over a mutative accumulation such as the above. Not only is a reduction "more abstract" -- it operates on the stream as a whole rather than individual elements -- but a properly constructed reduce operation is inherently parallelizable, so long as the function(s) used to process the elements are associative and stateless. For example, given a stream of numbers for which we want to find the sum, we can write:
int sum = numbers.stream().reduce(0, (x,y) -> x+y);
or:
int sum = numbers.stream().reduce(0, Integer::sum);
These reduction operations can run safely in parallel with almost no modification:
int sum = numbers.parallelStream().reduce(0, Integer::sum);
因此,对于您要使用的地图:
integers.values().stream().mapToInt(i -> i).reduce(0, (x,y) -> x+y);
或者:
integers.values().stream().reduce(0, Integer::sum);
我建议还有 2 个选项:
integers.values().stream().mapToInt(Integer::intValue).sum();
integers.values().stream().collect(Collectors.summingInt(Integer::intValue));
第二个使用 Collectors.summingInt()
收集器,还有一个 summingLong()
收集器,您可以将其与 mapToLong
一起使用。
第三个选项:Java 8 引入了一个非常有效的 LongAdder
累加器,旨在加速并行流和多线程环境中的汇总。在这里,这是一个使用示例:
LongAdder a = new LongAdder();
map.values().parallelStream().forEach(a::add);
sum = a.intValue();
这会起作用,但是 i -> i
正在执行一些自动拆箱,这就是它“感觉”奇怪的原因。 mapToInt
将流转换为 IntStream
“原始 int 值元素”。以下任一项都可以工作,并且可以更好地解释编译器使用您的原始语法在幕后做了什么:
integers.values().stream().mapToInt(i -> i.intValue()).sum();
integers.values().stream().mapToInt(Integer::intValue).sum();
你可以使用reduce方法:
long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, (x, y) -> x + y);
或
long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, Integer::sum);
您可以使用 collect 方法添加整数列表。
List<Integer> list = Arrays.asList(2, 4, 5, 6);
int sum = list.stream().collect(Collectors.summingInt(Integer::intValue));
您可以使用 reduce()
对整数列表求和。
int sum = integers.values().stream().reduce(0, Integer::sum);
这将是总结 int
类型数组的最短方法(对于 long
数组 LongStream
,对于 double
数组 DoubleStream
等等).不过,并非所有原始整数或浮点类型都具有 Stream
实现。
IntStream.of(integers).sum();
我已经声明了一个整数列表。
ArrayList<Integer> numberList = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));
您可以尝试使用以下这些不同的方式。
使用mapToInt
int sum = numberList.stream().mapToInt(Integer::intValue).sum();
使用summarizingInt
int sum = numberList.stream().collect(Collectors.summarizingInt(Integer::intValue)).getSum();
使用reduce
int sum = numberList.stream().reduce(Integer::sum).get().intValue();
希望对清单上有对象的人有所帮助。
如果您有一个对象列表并想对该对象的特定字段求和,请使用下面的方法。
List<ResultSom> somList = MyUtil.getResultSom();
BigDecimal result= somList.stream().map(ResultSom::getNetto).reduce(
BigDecimal.ZERO, BigDecimal::add);
不幸的是,流 API 看起来只有 returns 个来自 List<Integer>#stream()
的普通流。我猜他们是因为泛型的工作原理而被迫这样做。
这些普通的流是通用对象,所以没有像 sum()
等专门的方法,所以你必须默认使用奇怪的 re-stream “看起来像一个无操作”转换来获得对于那些方法... .mapToInt(i -> i)
.
另一个选项是使用“Eclipse Collections”,它类似于扩展的 java 流 API
IntLists.immutable.ofAll(integers.values()).sum();
List < Integer > listOfIntegers = List.of(1, 2, 10, 3, 4, 8, 5, 9, 6, 7);
Optional < Integer > maxValue = listOfIntegers
.stream().reduce((partialResult, currentValue) -> Math.max(partialResult, currentValue));
System.out.println("Maximum value : " + maxValue);
输出:最大值:可选[10]
这里还有一个没有人考虑的选项,它反映了 multi-core 环境的使用情况。如果你想利用它的优势,那么应该使用下一个代码而不是其他提到的解决方案:
int sum = integers.values().parallelStream().mapToInt(Integer::intValue)
.reduce(0, Integer::sum, Integer::sum);
这个方案和其他方案类似,但是请注意reduce中的第三个参数。它告诉编译器如何处理不同线程在流的不同块中计算的部分摘要。此外,使用 parallelStream()
而不是 stream()
。在这种情况下,它只会总结它。作为第三个参数的另一个选项是 (i, j) -> i + j
,这意味着它会将流块的值 (j
) 添加到当前值 (i
) 并将其用作下一个流块的当前值,直到处理完所有部分结果。
即使在使用普通 stream()
时,告诉减少如何处理流块的摘要也是有用的,以防万一有人或您将来想并行化它。最初的开发是最好的时机,因为稍后您需要记住它应该是什么,并且需要花一些时间再次理解该代码的用途。
当然,您可以使用不同的 lambda 方言来代替方法引用运算符。我更喜欢这种方式,因为它更紧凑,而且仍然易于阅读。
另请记住,这也可用于更复杂的计算,但请始终注意,无法保证流元素到线程的顺序和部署。