为什么IntStream.sum()返回一个int值?这是一些概念上的错误吗?从示例数组创建流时:
int A[] = {2^31-5, 2, 2, 2};
Run Code Online (Sandbox Code Playgroud)
所有元素的总和超过最大整数值,但不会抛出异常.有人知道如何预防这种情况吗?
默认情况下,如果发生溢出,Java中的积分算术不会抛出任何异常.溢出操作被截断为低位32位int,64位用于long.
如果要为溢出条件抛出异常,可以使用类中的"完全"函数族java.lang.Math:
addExactdecrementExactincrementExactmultiplyExactnegateExactsubtractExacttoIntExact这些被定义为与普通的算术运算相同int,long除了它们抛出ArithmeticException溢出而不是截断结果.
使用流,您的示例将如下所示:
int a[] = { Integer.MAX_VALUE - 5, 2, 2, 2 };
int sum = Arrays.stream(a).reduce(0, Math::addExact);
Run Code Online (Sandbox Code Playgroud)
这将抛出ArithmeticException.
(注意你的例子是书面使用2^31-5,它是一个有效的表达式,就像^XOR运算符一样.结果是24当然不会溢出.)
行为与int在循环中求和时得到的行为相匹配.有多种方法可以处理溢出,所有这些都是一般适用性和性能之间的权衡,因为API将/应该使用哪一个并不明显,所以选择了Java开发人员通常所知的那个. .
如果要使用更大的数据类型求和,可以使用其中任何一种
long sumL=IntStream.of(A).asLongStream().sum();// may still overflow
Run Code Online (Sandbox Code Playgroud)
要么
BigInteger sum = IntStream.of(A).mapToObj(BigInteger::valueOf)
.reduce(BigInteger.ZERO, BigInteger::add);// might be slower
Run Code Online (Sandbox Code Playgroud)
如果你想抛出行为,你可以使用
int sum=IntStream.of(A).reduce(0, (a,b)->{
int c=a+b;
if(a>0? b>0 && c<0: b<0&& c>0)
throw new ArithmeticException("overflow");
return c;
});
Run Code Online (Sandbox Code Playgroud)
或者,更简单(整合Stuart Marks的解决方案)
int sum=IntStream.of(A).reduce(0, Math::addExact);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1291 次 |
| 最近记录: |