Stream api reduce方法在尝试对大数求和时返回负值[重复]

Posted

技术标签:

【中文标题】Stream api reduce方法在尝试对大数求和时返回负值[重复]【英文标题】:Stream api reduce method returns negative value when trying to sum up large numbers [duplicate] 【发布时间】:2021-08-17 15:19:57 【问题描述】:

我正在尝试使用流 api reduce 方法对列表中的数字求和。它为较小的数字提供正确的结果。但是当我给出更大的数字时,它会返回一个不正确的负数。

这是我的代码

public void sumOfNum(List<Integer> numbers) 
    long result = numbers.stream().reduce(0, (a, b) -> a + b);
    System.out.print(result);

测试用例 1(通过)

输入

12345、2343、4324、2323、24234

输出

45569

测试用例 2(失败)

输入

256741038, 623958417,623958417,714532089, 714532089

输出

-1361245246

【问题讨论】:

【参考方案1】:

您将它们添加为整数,Java 对整数值 2147483647 有限制。 如果您通过此最大值,您将从最小值开始计数 Integer.MAX_VALUE + 1 = -2147483648.

【讨论】:

【参考方案2】:

您正在使用当前代码执行Integer 添加。我的假设是您知道可能发生的数字溢出,这就是long 类型为result 的原因。一旦您将流的值map 传递到Long,然后再对它们求和,事情就会到位。

long result = numbers.stream()
        .map(Long::valueOf)
        .reduce(0L, Long::sum);

或者简单地说:

long result = numbers.stream()
        .mapToLong(val -> val)
        .sum();

【讨论】:

哪个更好? mapToLong(val -&gt; val)mapToLong(Integer::longValue)。我假设val -&gt; val 涉及Integer -&gt; int -&gt; long 而第二个只是int -&gt; long? @Naman 是的,我知道整数溢出,但我是这个流 API 的新手,我完全忘记了我必须在 sum 之前将 Integer 转换为 long。现在它在将 Integer 转换为 long 后工作正常。谢谢。 @GauthamM 是的,尽管我的怀疑并不完全是你所说的。我怀疑4: i2l 的步骤,即 int 到 long 的转换也是 Integer.longValue 的一部分。没有足够的时间,但我肯定会尽快深入研究。 (在问题中将 Stream 分开,在我看来,这将超出基础知识) @GauthamM 没有区别,因为不可能有区别。源是Integer 对象,结果是long。唯一的区别是它发生在哪里。当您使用mapToLong(Integer::longValue)mapToLong(i -&gt; i.longValue()) 时,转换发生在Integer 类的longValue() 方法内。当您使用mapToLong(i -&gt; i) 时,转换发生在包含 lambda 主体的合成方法中。当您使用mapToLong(Integer::intValue) 时,转换发生在运行时生成的ToLongFunction 中。在所有情况下,代码路径都将包含 i2l @GauthamM 是的,但这对任何 JIT 编译器都没有挑战。它总是归结为读取Integer 的值字段并将其转换为long 值。

以上是关于Stream api reduce方法在尝试对大数求和时返回负值[重复]的主要内容,如果未能解决你的问题,请参考以下文章

为啥不在 Stream API 中使用 reduce 来合并多个映射?

Java 8新特性stream API用法总结

Java8学习笔记--Stream API详解[转]

Java 8 Stream API具体解释

流上的 reduce() 操作似乎正在修改数据源(列表)Stream API Java 8

Java 8 中的 Streams API 详解