Java IntStream.sum()异常处理

Java IntStream.sum()异常处理,java,java-8,Java,Java 8,为什么IntStream.sum()返回一个int值?这是概念上的错误吗?从示例性阵列创建流时: int A[] = {2^31-5, 2, 2, 2}; 所有元素的总和超过最大整数值,但不会引发异常。有人知道如何防止这种情况吗?这种行为与在循环中对ints求和时得到的结果相匹配。处理溢出的方法有很多种,它们都是通用性和性能之间的折衷。由于API将/应该使用哪种方法并不明显,所以选择了Java开发人员通常知道的方法 如果要使用较大的数据类型求和,可以使用 long sumL=IntStream

为什么
IntStream.sum()
返回一个int值?这是概念上的错误吗?从示例性阵列创建流时:

int A[] = {2^31-5, 2, 2, 2};

所有元素的总和超过最大整数值,但不会引发异常。有人知道如何防止这种情况吗?

这种行为与在循环中对
int
s求和时得到的结果相匹配。处理溢出的方法有很多种,它们都是通用性和性能之间的折衷。由于API将/应该使用哪种方法并不明显,所以选择了Java开发人员通常知道的方法

如果要使用较大的数据类型求和,可以使用

long sumL=IntStream.of(A).asLongStream().sum();// may still overflow

如果你想要投掷行为,你可以使用

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;
});

该行为与在循环中对
int
s求和时得到的结果相匹配。处理溢出的方法有很多种,它们都是通用性和性能之间的折衷。由于API将/应该使用哪种方法并不明显,所以选择了Java开发人员通常知道的方法

如果要使用较大的数据类型求和,可以使用

long sumL=IntStream.of(A).asLongStream().sum();// may still overflow

如果你想要投掷行为,你可以使用

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;
});

默认情况下,如果发生溢出,Java中的整数算法不会引发任何异常。溢出的操作对于
int
被截断为低位32位,对于
long
被截断为低位64位

如果希望针对溢出条件引发异常,可以使用类中的“精确”函数族:

  • addExact
  • 递减行为
  • incrementExact
  • multiplyExact
  • negateExact
  • subtractExact
  • toIntExact
这些被定义为与
int
long
上的普通算术运算相同,只是它们在溢出时抛出
算术异常,而不是截断结果

使用streams,您的示例如下所示:

int a[] = { Integer.MAX_VALUE - 5, 2, 2, 2 };
int sum = Arrays.stream(a).reduce(0, Math::addExact);
这将引发
算术异常


(请注意,您编写的示例使用了
2^31-5
,这是一个有效的表达式,因为
^
是异或运算符。结果是24,当然不会产生溢出。)

默认情况下,如果发生溢出,Java中的整数算法不会引发任何异常。溢出的操作对于
int
被截断为低位32位,对于
long
被截断为低位64位

如果希望针对溢出条件引发异常,可以使用类中的“精确”函数族:

  • addExact
  • 递减行为
  • incrementExact
  • multiplyExact
  • negateExact
  • subtractExact
  • toIntExact
这些被定义为与
int
long
上的普通算术运算相同,只是它们在溢出时抛出
算术异常,而不是截断结果

使用streams,您的示例如下所示:

int a[] = { Integer.MAX_VALUE - 5, 2, 2, 2 };
int sum = Arrays.stream(a).reduce(0, Math::addExact);
这将引发
算术异常


(请注意,您编写的示例使用了
2^31-5
,这是一个有效的表达式,因为
^
是异或运算符。结果是24,当然不会产生溢出。)

为什么会引发异常?如果您需要一个
long
,您必须这样做。为什么会抛出异常?如果你需要一个
长的
,你就必须这么做。@Boris蜘蛛:我怎么能忘记这个…Thanks@Boris蜘蛛:我怎么能忘记呢…谢谢我觉得有(一定有)这样的方法,但我搜索了
java.lang.Integer
,因为我知道它有
sum
方法,对于另一种求和方法,没有考虑
java.lang.Math
。这就是为什么我写了一个手动检查作为lambda表达式。类位置和方法名的决定背后是否有一种模式可以帮助我在将来找到这样的方法?@Holger是的,我知道这些函数已经添加,我首先查找的是
java.lang.Integer
。我在
java.lang.Math
中发现它们时有点惊讶。在某种程度上,这是一个判断此类行动走向的问题。在
Math
中已经有很多基本操作,例如
abs()
max()
,超越,
round()
signum()
,等等,有些操作对不同的基本体具有重载,因此将“精确”操作也放入
Math
中似乎是合理的。我觉得有一些(必须是)这样一个方法,但是我搜索了
java.lang.Integer
,因为我知道它有
sum
方法,作为一个可选的sum方法,并且没有考虑
java.lang.Math
。这就是为什么我写了一个手动检查作为lambda表达式的原因。在决定类位置和方法名称之后是否有一种模式可以帮助我将来要找到这样的方法吗?@Holger是的,我知道这些函数已经被添加了,我首先查找的地方是
java.lang.Integer
。在
java.lang.Math
中找到它们,我有点惊讶。在某种程度上,这是一个判断这些操作去哪里的问题。中已经有很多原始操作了e> 数学
,例如
abs()
max()
,超越性,
round()
signum()
,等等,其中一些对不同的原语具有重载,因此将“精确”操作也放入
Math
似乎是合理的。