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

mem*_*und 338 java java-8 java-stream

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

Map<String, Integer> integers;
integers.values().stream().mapToInt(i -> i).sum();
Run Code Online (Sandbox Code Playgroud)

Nec*_*aux 465

这样可行,但是i -> i正在做一些自动拆箱,这就是它"感觉"奇怪的原因.下面的任何一个都可以使用原始语法更好地解释编译器在做什么:

integers.values().stream().mapToInt(i -> i.intValue()).sum();
integers.values().stream().mapToInt(Integer::intValue).sum();
Run Code Online (Sandbox Code Playgroud)

  • 一个简单的选择是BigDecimal sum = numbers.stream()。reduce(BigDecimal.ZERO,BigDecimal :: add); (5认同)
  • 如果我们有一个BigInteger :)怎么办? (2认同)
  • 如何求和得出特定值?例如,您有一个整数列表,但您想要求和直到得到值 20。 (2认同)

Ale*_*you 145

我建议另外2个选项:

integers.values().stream().mapToInt(Integer::intValue).sum();
integers.values().stream().collect(Collectors.summingInt(Integer::intValue));
Run Code Online (Sandbox Code Playgroud)

第二个使用Collectors.summingInt()收集器,还有一个summingLong()收集器,您将使用它mapToLong.


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

LongAdder a = new LongAdder();
map.values().parallelStream().forEach(a::add);
sum = a.intValue();
Run Code Online (Sandbox Code Playgroud)


J A*_*kin 82

来自文档

缩减操作缩小操作(也称为折叠)采用一系列输入元素,并通过重复应用组合操作将它们组合成单个汇总结果,例如查找一组数字的总和或最大值,或将元素累积到一个列表.流类具有多种形式的通用缩减操作,称为reduce()和collect(),以及多种专用缩减形式,如sum(),max()或count().

当然,这样的操作可以很容易地实现为简单的顺序循环,如:

int sum = 0;
for (int x : numbers) {
   sum += x;
}
Run Code Online (Sandbox Code Playgroud)

然而,有充分理由优先考虑减少操作而不是如上所述的变异累积.简化不仅"更抽象" - 它作为一个整体而不是单个元素在整个流上运行 - 但正确构造的reduce操作本质上是可并行化的,只要用于处理元素的函数是关联的和无国籍的.例如,给定我们想要找到总和的数字流,我们可以写:

int sum = numbers.stream().reduce(0, (x,y) -> x+y);
Run Code Online (Sandbox Code Playgroud)

要么:

int sum = numbers.stream().reduce(0, Integer::sum);
Run Code Online (Sandbox Code Playgroud)

这些减少操作可以安全地并行运行,几乎不需要修改:

int sum = numbers.parallelStream().reduce(0, Integer::sum);
Run Code Online (Sandbox Code Playgroud)

因此,对于您将使用的地图:

integers.values().stream().mapToInt(i -> i).reduce(0, (x,y) -> x+y);
Run Code Online (Sandbox Code Playgroud)

要么:

integers.values().stream().reduce(0, Integer::sum);
Run Code Online (Sandbox Code Playgroud)

  • (x,y) - > x + y需要unbox x和y,求和,然后将结果打包.然后重新开始添加结果与流的下一个元素,并一次又一次. (6认同)
  • Integer :: sum遇到同样的问题.如果使用mapToInt()来创建IntStream,则调用sum()比调用reduce()更简单. (3认同)
  • 请参见http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#sum-int-int-.Integer.sum()的两个参数是int类型.因此,流中的两个整数必须取消装箱才能作为参数传递给方法.该方法返回一个int,但reduce()将BinaryOperator <Integer>作为参数,从而返回一个Integer.所以总和的结果必须加到Integer中. (3认同)
  • OP的功能更好,也更清晰.这段代码将涉及一整套拆箱和装箱操作. (2认同)

Sae*_*fam 27

您可以使用reduce方法:

long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, (x, y) -> x + y);
Run Code Online (Sandbox Code Playgroud)

要么

long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, Integer::sum);
Run Code Online (Sandbox Code Playgroud)

  • 对于`int`已经存在这样的累加器,它是`Integer :: sum` (9认同)

小智 16

您可以使用reduce()对整数列表求和.

int sum = integers.values().stream().reduce(0, Integer::sum);
Run Code Online (Sandbox Code Playgroud)


小智 11

您可以使用collect方法添加整数列表.

List<Integer> list = Arrays.asList(2, 4, 5, 6);
int sum = list.stream().collect(Collectors.summingInt(Integer::intValue));
Run Code Online (Sandbox Code Playgroud)


Sac*_*lla 6

This would be the shortest way to sum up int type array (for long array LongStream, for double array DoubleStream and so forth). Not all the primitive integer or floating point types have the Stream implementation though.

IntStream.of(integers).sum();
Run Code Online (Sandbox Code Playgroud)


JDG*_*ide 6

我已经声明了一个整数列表。

ArrayList<Integer> numberList = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));
Run Code Online (Sandbox Code Playgroud)

您可以尝试使用以下这些不同的方法。

使用 mapToInt

int sum = numberList.stream().mapToInt(Integer::intValue).sum();
Run Code Online (Sandbox Code Playgroud)

使用 summarizingInt

int sum = numberList.stream().collect(Collectors.summarizingInt(Integer::intValue)).getSum();
Run Code Online (Sandbox Code Playgroud)

使用 reduce

int sum = numberList.stream().reduce(Integer::sum).get().intValue();
Run Code Online (Sandbox Code Playgroud)


itr*_*tro 6

愿这对那些在清单上有对象的人有所帮助。

如果您有一个对象列表并想对该对象的特定字段求和,请使用以下内容。

List<ResultSom> somList = MyUtil.getResultSom();
BigDecimal result= somList.stream().map(ResultSom::getNetto).reduce(
                                             BigDecimal.ZERO, BigDecimal::add);
Run Code Online (Sandbox Code Playgroud)