本文翻译自:How to sum a list of integers with java streams?
I want to sum a list of integers. 我想总结一个整数列表。 It works as follows, but the syntax does not feel right. 它的工作原理如下,但语法感觉不对。 Could the code be optimized? 代码可以优化吗?
Map integers;
integers.values().stream().mapToInt(i -> i).sum();
参考:https://stackoom.com/question/22Oxs/如何用java流汇总整数列表
From the 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(). 流类具有多种形式的通用缩减操作,称为reduce()和collect(),以及多种专用缩减形式,如sum(),max()或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. 简化不仅“更抽象” - 它作为一个整体而不是单个元素在整个流上运行 - 但正确构造的reduce操作本质上是可并行化的,只要用于处理元素的函数是关联的和无国籍的。 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);
So, for a map you would use: 因此,对于您将使用的地图:
integers.values().stream().mapToInt(i -> i).reduce(0, (x,y) -> x+y);
Or: 要么:
integers.values().stream().reduce(0, Integer::sum);
I suggest 2 more options: 我建议另外2个选项:
integers.values().stream().mapToInt(Integer::intValue).sum();
integers.values().stream().collect(Collectors.summingInt(Integer::intValue));
The second one uses Collectors.summingInt()
collector, there is also a summingLong()
collector which you would use with mapToLong
. 第二个使用Collectors.summingInt()
收集器,还有一个summingLong()
收集器,您可以将其与mapToLong
一起使用。
And a third option: Java 8 introduces a very effective LongAdder
accumulator designed to speed-up summarizing in parallel streams and multi-thread environments. 第三种选择:Java 8引入了一个非常有效的LongAdder
累加器,旨在加速并行流和多线程环境中的汇总。 Here, here's an example use: 这里是一个使用示例:
LongAdder a = new LongAdder();
map.values().parallelStream().forEach(a::add);
sum = a.intValue();
This will work, but the i -> i
is doing some automatic unboxing which is why it "feels" strange. 这样可行,但是i -> i
正在做一些自动拆箱,这就是它“感觉”奇怪的原因。 Either of the following will work and better explain what the compiler is doing under the hood with your original syntax: 下面的任何一个都可以使用原始语法更好地解释编译器在做什么:
integers.values().stream().mapToInt(i -> i.intValue()).sum();
integers.values().stream().mapToInt(Integer::intValue).sum();
You can use reduce method: 您可以使用reduce方法:
long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, (x, y) -> x + y);
or 要么
long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, Integer::sum);
You can use collect method to add list of integers. 您可以使用collect方法添加整数列表。
List list = Arrays.asList(2, 4, 5, 6);
int sum = list.stream().collect(Collectors.summingInt(Integer::intValue));