如何使用Java Streams对整数列表求和?

480

我想对整数列表进行求和。以下是代码示例,但语法不太对。这段代码能否进行优化?

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

7
您认为语法不正确的原因是什么?这是通常的习语。也许根据您的映射可能具有的值,您想使用mapToLong来避免溢出。 - Alexis C.
3
个人而言,我认为“i -> i”非常清晰。是的,你需要知道这个值将自动拆箱,但自从Java 5以来就是这样了。 - Alexis C.
4
@AlexisC. 这个代码很好理解,因为它被传递给了mapToInt()函数并且我是一位有经验的开发者。但是,如果没有上下文,i -> i看起来像一个空操作。使用Integer::intValue更长,但是使拆箱操作更加明确。 - JB Nizet
1
@JBNizet 调用方法 foo(int i) 的人不会每次调用它时都写 foo(myInteger.intValue());(或者至少我希望如此!!)。我同意您的看法,即 Integer::intValue 更加明确,但我认为同样适用于这里。人们只需要学习一次,然后就完成了 :-)。这不像是一些神奇的混淆技术。 - Alexis C.
4
@JB Nizet: "i -> i"看起来像是一个no-op(无操作),在概念上,它确实是一个no-op。当然,在底层会调用Integer.intValue() 方法,但更深入底层,该方法会被内联成与源代码中看起来完全一样的no-op。 使用 Integer :: intValue 有额外的好处,即不会在字节码中创建合成方法,但这不应驱动您决定如何组织源代码。 - Holger
显示剩余2条评论
13个回答

2

很遗憾,似乎Stream API只能从普通流中返回,例如List<Integer>#stream()。 猜测他们必须这样做是因为泛型的工作方式。

这些普通的Streams是泛型对象,因此没有像sum()等专门的方法,因此您必须默认使用奇怪的重新流“看起来像无操作”的转换才能获得这些方法…….mapToInt(i -> i)

另一个选择是使用“Eclipse Collections”,它们类似于扩展的Java Stream API

IntLists.immutable.ofAll(integers.values()).sum();


1
IntStream.of(1, 2, 23).sum();
IntStream.of(1, 2, 23,1, 2, 23,1, 2, 23).max().getAsInt();

0
使用 summingInt
Integer sum= listInt.stream().collect(Collectors.summingInt(Integer::intValue));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接