我有一个整数数组,想要对它的所有元素求和。只要sum小于或等于int max value(2147483647),它就能正常工作,但是当sum超过int max value时它会失败。以下是示例 - :
int [] iArr = new int[]{2147483646 , 1 , 1};
System.out.println(Arrays.stream(iArr).sum());
结果 - :-2147483648
我们可以看到上面的结果不正确。我知道如果使用int数组,可以通过使用long数组来解决它。
long [] iArr = new long[]{2147483646 , 1 , 1};
System.out.println(Arrays.stream(iArr).sum());
结果 - :2147483648
但我不想使用长数组,因为我知道数组元素的最大大小限制在int max value(2147483647)中。因此我不想浪费记忆。有没有其他方法可以使用Array Stream对整数数组求和(数组元素之和)超过int max value(2147483647)?
答案 0 :(得分:5)
您不需要long[]
数组,只需将值处理为long
s。解决方案就像人们想象的那样简单:
int[] iArr = new int[]{2147483646 , 1 , 1};
System.out.println(Arrays.stream(iArr).asLongStream().sum());
它不可能超过long
范围,因为即使所有元素都与Integer.MAX_VALUE
一样大,您也需要4294967298个流元素才能到达Long.MAX_VALUE
。但是如果你有这么大的流和很多时间,或者LongStream
是你的起点,你可以按照以下方式求助BigInteger
:
long[] lArr={ Long.MAX_VALUE, Long.MAX_VALUE, 42 };
System.out.println(Arrays.stream(lArr).mapToObj(BigInteger::valueOf)
.reduce(BigInteger.ZERO, BigInteger::add));
请注意,这也适用于IntStream
,因为从int
到long
的促销会在调用BigInteger.valueOf(long)
时自动发生,但如上所述,这很少需要
答案 1 :(得分:3)
这个问题已经得到解答,但我找到了另一种最佳完成上述任务的方法。这就是我想与执行时间统计分享的原因。流的 asLongStream 方法最佳地将整数流转换为long。
int[] iArr = new int[10000000];
Arrays.fill(iArr , 3132);
long iStart = System.nanoTime();
long lSum1 = Arrays.stream(iArr).mapToLong(Long::valueOf).sum();
long iEnd = System.nanoTime();
System.out.println("Sum-: " + lSum1);
System.out.println("Time in nanoseconds-: " + (iEnd - iStart) + "ns using \"mapToLong\"\n");
long iStart1 = System.nanoTime();
long lSum2 = Arrays.stream(iArr).asLongStream().sum();
long iEnd1 = System.nanoTime();
System.out.println("Sum-: " + lSum2);
System.out.println("Time in nanoseconds-: " + (iEnd1 - iStart1) + "ns using \"asLongStream\"\n");
long iStart2 = System.nanoTime();
long lSum3 = Arrays.stream(iArr).boxed().collect(Collectors.summingLong(Integer::longValue));
long iEnd2 = System.nanoTime();
System.out.println("Sum-: " + lSum3);
System.out.println("Time in nanoseconds-: " + (iEnd2 - iStart2) + "ns using \"Collectors\"\n");
输出 - :
总和 - :31320000000
以纳秒为单位的时间 - :230369419ns,使用“mapToLong”
总和 - :31320000000
以纳秒为单位的时间 - :109999469ns,使用“asLongStream”
总和 - :31320000000
以纳秒为单位的时间 - :188769476ns使用“收藏家”
答案 2 :(得分:2)
如果long足够大以保持结果,那么你可以使用收集器将值加总为long:
Arrays.stream(is).boxed()
.collect(Collectors.summingLong(Integer::longValue));
如果你需要更长的时间,你可能需要使用BigInteger,如下所示:
Arrays.stream(is).boxed()
.map(Integer::longValue)
.collect(Collectors
.reducing(new BigInteger("0"), BigInteger::valueOf, (b1, b2) -> b1.add(b2)));
答案 3 :(得分:1)
问题是sum的返回类型与流的类型匹配。如果先将它映射到Longs流,那么可以正确返回总和。
int [] iArr = new int[]{2147483646 , 1 , 1};
Long sum = Arrays.stream(iArr)
.mapToLong(Long::valueOf)
.sum();
System.out.println(sum);