如果使用Arrays Stream,整数数组的总和是否超过int max value(2147483647)?

时间:2016-11-24 04:50:16

标签: arrays java-8 java-stream

我有一个整数数组,想要对它的所有元素求和。只要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)?

4 个答案:

答案 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,因为从intlong的促销会在调用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);