Java 8之Stream適用場景

Stream是Java 8中的一個大的改進。Stream的功能是,支持集合的各種操作,比如filter, sum, max, min, average, map, reduce等等。所以我個人認爲Stream的出現是基於以下原因:

  • 增強集合操作
  • 擁抱函數式編程
  • 充分利用Lambda
  • 執行效率的提高 - 透明支持多線程集合操作

筆者嘗試測試一下Stream併發處理的威力,發現面對特別簡單的任務,Stream併發處理相較於傳統的for each循環,執行效率沒有優勢。看起來Stream不是免費的午餐,創建Stream還是要一些開銷的。所以這促使筆者思考該在什麼場景下才使用Stream。

測試例子

筆者測試兩個例子,一個任務非常簡單,另外一個稍微複雜一點。從結果看起來,並行Stream總是比串行快,任務簡單的情況,For Loop更快,任務複雜一點,並行Stream後來居上,並行帶來的改進足以cover創建Stream的開銷。

測試的小工具類

public class TimeRecorder {
    private long startTime;
    private long endTime;

    public void start() {
        startTime = System.currentTimeMillis();
    }

    public long end() {
        endTime = System.currentTimeMillis();
        return endTime - startTime;
    }

    public long getDuration() {
        return endTime - startTime;
    }

}

任務非常簡單的例子

只調用intValue這麼一個小方法。

public class StreamDemoSimple {
    public static void main(String[] args) {
        List<Integer> intList = new LinkedList<Integer>();
        for (int i = 1; i <= 1000000; i++) {
            intList.add(i);
        }

        TimeRecorder recorder = new TimeRecorder();

        recorder.start();
        intList.stream().forEach(i -> {
            i.intValue();
        });
        recorder.end();
        System.out.print("Stream iterator:");
        System.out.println(recorder.getDuration());

        recorder.start();
        intList.parallelStream().forEach(i -> {
            i.intValue();
        });
        recorder.end();
        System.out.print("Parallel Stream iterator:");
        System.out.println(recorder.getDuration());

        recorder.start();
        for (Integer i : intList) {
            i.intValue();
        }
        recorder.end();
        System.out.print("Normal iterator:");
        System.out.println(recorder.getDuration());
    }
}

輸出如下:

Stream iterator:447
Parallel Stream iterator:142
Normal iterator:70

任務稍微複雜的例子

多執行了幾步而已。

public class StreamDemo {
    public static void main(String[] args) {
        List<Integer> intList = new LinkedList<Integer>();
        for (int i = 1; i <= 1000000; i++) {
            intList.add(i);
        }

        TimeRecorder recorder = new TimeRecorder();

        recorder.start();
        intList.stream().forEach(i -> {
            i.intValue();
            i.intValue();
            i.toString();

            i.intValue();
            i.intValue();
            i.toString();
        });
        recorder.end();
        System.out.print("Stream iterator:");
        System.out.println(recorder.getDuration());

        recorder.start();
        intList.parallelStream().forEach(i -> {
            i.intValue();
            i.intValue();
            i.toString();

            i.intValue();
            i.intValue();
            i.toString();
        });
        recorder.end();
        System.out.print("Parallel Stream iterator:");
        System.out.println(recorder.getDuration());

        recorder.start();
        for (Integer i : intList) {
            i.intValue();
            i.intValue();
            i.toString();

            i.intValue();
            i.intValue();
            i.toString();
        }
        recorder.end();
        System.out.print("Normal iterator:");
        System.out.println(recorder.getDuration());
    }
}

輸出如下:

Stream iterator:808
Parallel Stream iterator:313
Normal iterator:377

Stream的適合場景

  • 集合操作超過兩個步驟
    比如先filter再for each
    這時Stream顯得優雅簡潔,效率也高
  • 任務較重,注重效能,希望併發執行
    很容易的就隱式利用了多線程技術。非常好的使用時機。
  • 函數式編程的編碼風格里
    Stream的設計初衷之一

結語

Lambda,Stream等等新特性使得Java函數式編程更爲自然。合適的環境下非常值得合理使用。但是請記住Stream的創建以及傳輸也有損耗,特別簡單的場景可能傳統的For Loop更爲適合。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章