Java 8 | Stream (下)
Stream
的另一個價值是創造性地支持並行處理(parallel processing
)。Stream
操作可以是順序的,也可以是並行的。順序操作通過單線程執行,而並行操作則通過多線程執行。
並行(parallel)程序
parallelStream
是流並行處理程序的代替方法。以下實例我們使用parallelStream
來輸出空字符串的數量:(可以很容易的在順序運行和並行直接切換)
1 | List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); |
註:這邊一定會有疑問到底Stream和Parallel差在哪邊,可以參考這篇文章Stream 與平行化,有更詳細的說明。
下面的例子就演示瞭如何使用並行流進行操作來提高運行效率,程式碼非常簡單。
首先我們創建一個大的list,裡面的元素都是唯一的:
1 | int max = 1000000; |
- 順序排序
1 | long t0 = System.nanoTime(); |
- 並行排序
1 | long t0 = System.nanoTime(); |
如你所見,所有的程式碼段幾乎都相同,唯一的不同就是把stream()
改成了parallelStream(),結果並行排序快了
50%`。
Collectors
Collectors
類實現了很多歸約操作,例如將流轉換成集合和聚合元素。Collectors
可用於返回列表或字符串:
1 | List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); |
輸出的結果為:
1 | 篩選列表: [abc, bc, efg, abcd, jkl] |
範例
對於上一篇的tasks
集合,我們可以用下面的程式碼計算所有任務的點數之和:
1 | // Calculate total points of all tasks |
這裡我們使用parallel
方法並行處理所有的task
,並使用reduce
方法計算最終的結果。輸出如下:
1 | Total points(all tasks): 26.0 |
對於一個集合,經常需要根據某些條件對其中的元素分組。利用stream
提供的API
可以很快完成這類任務,程式碼如下:
1 | // Group tasks by their status |
輸出的結果為:
1 | {CLOSED=[[CLOSED, 8]], OPEN=[[OPEN, 5], [OPEN, 13]]} |
最後關於tasks
集合的例子問題是:如何計算集合中每個任務的點數在集合中所佔的比重,具體處理的程式碼如下:
1 | // Calculate the weight of each tasks (as percent of total points) |
輸出的結果為:
1 | [19%, 50%, 30%] |
最後,正如之前所說,Stream API
不僅可以作用於Java
集合,傳統的IO
操作(從文件或者網路一行一行得讀取資料)可以受益於stream
處理,這裡有一個小例子:
1 | final Path path = new File( filename ).toPath(); |
Stream
的方法onClose
返回一個等價的有額外句柄的Stream
,當Stream
的close()
方法被調用的時候這個句柄會被執行。Stream API
、Lambda
表達式還有接口默認方法和靜態方法支持的方法引用,是Java 8
對軟件開發的現代範式的響應。
註:以上參考了
Stream 與平行化
Java 8 Lambda新語法,簡化程式,增強效能
Java 8 新特性
Java 8的新特性—终极版
现代化 Java - Java8 指南