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更爲適合。