【问题标题】:why java stream sum api returns the sum in same data type and not a bigger one?为什么 java stream sum api 返回相同数据类型的总和而不是更大的总和?
【发布时间】:2020-03-07 19:50:52
【问题描述】:

我有一些使用 Arrays.stream(int arr[]).sum() 添加的整数。它返回 int 中截断的总和,而实际总和更大并且适合 long。为什么流 API 通过截断只返回 int 而不是 long?

尝试过像 int myArray[] = { 1, 5, 8 }; 这样的小整数 int sum = Arrays.stream(myArray).sum();

工作正常。

但不适用于总和为 long 的较长整数。

下面的场景 1 工作正常并返回 14

int myArray[] = { 1, 5, 8 };
int sum = Arrays.stream(myArray).sum();

而方案 2 将无法工作,因为总和超过 32 位。它给出的总和为 -105032716,而预期为 4189934580

int myArray[] = { 2094967290, 2094967290};
int sum = Arrays.stream(myArray).sum();

为了得到正确的总和,如果我在下面做,我会得到预期的结果 4189934580

long sum = 0L + 2094967290+2094967290;
System.out.println(sum);

【问题讨论】:

  • 我没有参与它的规范,所以我只能猜测:可能他们不想总是做一个long加法(包括转换),即使它显然不需要。所以选择留给开发人员,就像简单的添加一样。

标签: java java-stream


【解决方案1】:

您正在对 int(s) 求和(一种 32 位原始数据类型)。如果你想要一个long,求和long(s)。这就是原始数学的工作原理。

int c = 2094967290 + 2094967290;
System.out.println(c);

和

一样
System.out.println(2094967290 + 2094967290);

使用long(s)

System.out.println(2094967290 + 2094967290L);

或者像这样的流将在这里产生正确的结果

long sum = Arrays.stream(myArray).mapToLong(Long::valueOf).sum();

或(如comments中指出的那样)

long sum = Arrays.stream(myArray).asLongStream().sum();

但是,long 也可能溢出(它是 64 位原始数据类型)。对于任意精度,您应该使用BigInteger。

BigInteger sum = Arrays.stream(myArray).mapToObj(BigInteger::valueOf)
        .reduce(BigInteger.ZERO, (a, b) -> a.add(b));

【讨论】:

  • asLongStream() 会 更简单 而不是 mapToLong
  • @CarlosHeuberger 确实如此。
【解决方案2】:

这取决于开发人员。你知道会发生什么,你正在处理什么数据,更重要的是,你测试它。在我看来,这与我们处理任何intOne + intTwo 可能溢出的方式没有什么不同。

如果知道总和会超出int 范围,则切换到长流(感谢Carlos Heuberger 为asLongStream() 而不是mapToLong(i -> i)):

long sum = Arrays.stream(myArray).asLongStream().sum();

【讨论】:

  • asLongStream() 会更简单
猜你喜欢
  • 2010-12-22
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多