如何用java流汇总整数列表?

问题

我想总结一个整数列表。它的工作原理如下,但语法感觉不对。代码可以优化吗?

Map<String, Integer> integers;
integers.values().stream().mapToInt(i -> i).sum();

#1 热门回答(305 赞)

这将有效,但i -> i正在做一些自动拆箱,这就是为什么它"感觉"奇怪。下面的任何一个都可以使用原始语法更好地解释编译器在底层所做的事情:

integers.values().stream().mapToInt(i -> i.intValue()).sum();
integers.values().stream().mapToInt(Integer::intValue).sum();

#2 热门回答(108 赞)

我建议另外2个选项:

integers.values().stream().mapToInt(Integer::intValue).sum();
integers.values().stream().collect(Collectors.summingInt(Integer::intValue));

第二个使用Collectors.summingInt()collector,还有一个asummingLong()collector,你可以使用mapToLong

第三种选择:Java 8引入了一种非常有效的LongAdder累积器,旨在加速并行流和多线程环境中的汇总。这里是一个使用示例:

LongAdder a = new LongAdder();
map.values().parallelStream().forEach(a::add);
sum = a.intValue();

#3 热门回答(56 赞)

docs

缩减操作缩小操作(也称为折叠)采用一系列输入元素,并通过重复应用组合操作将它们组合成单个汇总结果,例如查找一组数字的总和或最大值,或累积元素进入一个清单。流类具有多种形式的通用缩减操作,称为reduce()和collect(),以及多种专用缩减形式,如sum(),max()或count()。当然,这样的操作可以很容易地实现为简单的顺序循环,如:int sum = 0;
for(int x:numbers){
   sum = x;
}
 然而,有充分理由优先考虑减少操作而不是如上所述的变异累积。简化不仅"更抽象" - 它作为一个整体而不是单个元素在整个流上运行 - 但正确构造的reduce操作本质上是可并行化的,只要用于处理元素的函数是关联的和无国籍的。例如,给定一个我们想要求和的数字流,我们可以写:int sum = numbers.stream()。reduce(0,(x,y) - > x y);
 或:int sum = numbers.stream()。reduce(0,Integer :: sum);
 这些简化操作可以安全地并行运行,几乎不需要修改:int sum = numbers.parallelStream()。reduce(0,Integer :: sum);

因此,对于你将使用的 Map :

integers.values().stream().mapToInt(i -> i).reduce(0, (x,y) -> x+y);

要么:

integers.values().stream().reduce(0, Integer::sum);