簡體   English   中英

Java 8 Stream.sum()的錯誤行為

[英]Erroneous behaviour of Java 8 Stream.sum()

今天在HackerRank上解決這個問題時,我使用了Array stream .sum()函數對所有條目求和並繼續我的算法。 但總而言之,我發現我的算法在某些情況下失敗了。 我使用diff來發現它通過了99%的情況,1%的輸出幾乎相等,但小於原始答案。 這就是為什么我用for循環替換了流.sum(),並且意外地它通過了所有的測試用例。 我試過但無法確定這種不確定的行為。

我使用stream.sum()的實現:

public class MandragoraForest {

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        for (int i = in.nextInt(); i > 0; i--) {
            int number = in.nextInt();
            int[] h = new int[number];
            for (int j = 0; j < number; j++) h[j] = in.nextInt();
            System.out.println(new MandragoraForestSolver().solve(h));
        }
    }
}

class MandragoraForestSolver {

    public long solve(int[] h) {
        if (h.length==1) return h[0];
        Arrays.parallelSort(h);
        long sum = Arrays.stream(h)
                .sum();
        long ans = -1;

        for (long i=0, strength = 2; i<h.length; i++, strength++) {
            sum -= h[(int)i];
            ans = Math.max(ans, strength * sum);
        }
        return ans;
    }
}

沒有Java流的實現:

public class MandragoraForest {

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        for (int i = in.nextInt(); i > 0; i--) {
            int number = in.nextInt();
            int[] h = new int[number];
            long sum = 0;
            for (int j = 0; j < number; j++) {
                h[j] = in.nextInt();
                sum += h[j];
            }
            System.out.println(new MandragoraForestSolver().solve(h, sum));
        }
    }
}

class MandragoraForestSolver {

    public long solve(int[] h, long sum) {
        if (h.length==1) return h[0];
        Arrays.parallelSort(h);


        long ans = -1;

        for (long i=0, strength = 2; i<h.length; i++, strength++) {
            sum -= h[(int)i];
            ans = Math.max(ans, strength * sum);
        }
        return ans;
    }
}

有什么東西我錯過了嗎? 這種行為可能是什么原因?

使用流和循環之間存在一個顯着差異 - 算術溢出的可能性。

Arrays.stream(int[])返回一個IntStream ,其sum()方法返回一個int結果。 如果總和超過Integer.MAX_VALUE ,則會發生靜默整數溢出。

但是,你的循環總和是通過將int值添加到一個long int ,這不會受到算術溢出的影響。

其中一個測試中的整數之和必須超過Integer.MAX_VALUE ,測試long用於(正確)計算總數。


如果要使用流來求和,則需要將IntStream轉換為LongStream ,您可以這樣做:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM