Dating Java8系列之Java8中的‘流’

翎野君/文

圖片

 

圖片

流的概念

 

1.流是什麼

流是Java API的新成員,它允許你以聲明性方式處理數據集合(通過查詢語句來表達,而不是臨時編寫一個實現)。就現在來說,我們可以把它們看成遍歷數據集的高級迭代器。

 

代碼:按價格排序後得到手機名稱列表

 

使用新的流式方法有幾個顯而易見的好處。

  • 代碼是以聲明性方式寫的:說明想要完成什麼而不是說明如何實現一個操作(如利用循環和if條件等控制流語句)。

  • 我們可以把幾個基礎操作鏈接起來,來表達複雜的數據處理流水線(在filter後面接上 sorted、map和collect操作,如圖4-1所示),同時保持代碼清晰可讀。filter的結果 被傳給了sorted方法,再傳給map方法,最後傳給collect方法。

圖片

 

2.流簡介

‘流’的簡單定義就是“從支持數據處理操作的源生成的元素序列”。

 

  • 元素序列——就像集合一樣,流也提供了一個接口,可以訪問特定元素類型的一組有序值。因爲集合是數據結構,所以它的主要目的是以特定的時間/空間複雜度存儲和訪問元素(如ArrayList與LinkedList)。但流的目的在於表達計算,比如你前面見到的 filter、sorted和map。集合講的是數據,流講的是計算。

  • 源——流會使用一個提供數據的源,如集合、數組或輸入/輸出資源。請注意,從有序集 合生成流時會保留原有的順序。由列表生成的流,其元素順序與列表一致。

  • 數據處理操作——流的數據處理功能支持類似於數據庫的操作,以及函數式編程語言中的常用操作,如filter、map、reduce、find、match、sort等。流操作可以順序執行,也可並行執行。

 

3.流的特點

流的兩個重要特點

  • 流水線——很多流操作本身會返回一個流,這樣多個操作就可以鏈接起來,形成一個大的流水線。流水線的操作可以看作對數據源進行數據庫式查詢。

  • 內部迭代——與使用迭代器顯式迭代的集合不同,流的迭代操作是在背後進行的。

 

圖片

流與集合

 

1.流和集合之間的差異

集合與流之間的差異在於什麼時候進行計算。

  • 集合是一個內存中的數據結構,它包含數據結構中目前所有的值,集合中的每個元素都得先算出來才能添加到集合中。即,可以往集合里加東西或者刪東西,但是不管什麼時候,集合中的每個元素都是放在內存裏的,元素都得先算出來才能成爲集合的一部分。

  • 相比之下,流則是在概念上固定的數據結構(你不能添加或刪除元素),其元素則是按需計算的。 從另一個角度來說,流就像是一個延遲創建的集合:只有在消費者要求的時候纔會計算值。

 

2.注意事項

請注意,和迭代器類似,流只能遍歷一次。遍歷完之後,我們就說這個流已經被消費掉了。 

 

3.遍歷數據時的區別

集合和流的另一個關鍵區別在於它們遍歷數據的方式。

使用Collection接口需要用戶去做迭代(比如用for-each),這稱爲外部迭代。

相反,Streams庫使用內部迭代——它幫你把迭代做了,還把得到的流值存在了某個地方,我們只要給出 一個函數說要幹什麼就可以了。

  • 使用for-each循環外部迭代

  • 使用其背後的迭代器做外部迭代

  • 使用流做內部迭代

 

圖片

 

圖片

流操作

 

java.util.stream.Stream中的Stream接口定義了許多操作。它們可以分爲兩大類。 

 

你可以看到兩類操作:

  • filter、map和limit可以連成一條流水線;  

  • collect觸發流水線執行並關閉它。

可以連接起來的流操作稱爲中間操作,關閉流的操作稱爲終端操作。

 

中間操作:諸如filter或sorted等中間操作會返回另一個流。這讓多個操作可以連接起來形成一個查詢。更重要的是,除非流水線上觸發一個終端操作,否則中間操作不會執行任何處理——它們很懶。這是因爲中間操作一般都可以合併起來,在終端操作時一次性全部處理。

終端操作:終端操作會從流的流水線生成結果。其結果是任何不是流的值,比如List、Integer,或者void。

 

圖片

使用流

 

總而言之,流的使用一般包括三件事:

  • 一個數據 (如集合)來執行一個查詢;

  • 一箇中間操作鏈,形成一條流的流水線;

  • 一個終端操作,執行流水線,並能生成結果。

 

流的流水線背後的理念類似於構建器模式。在構建器模式中有一個調用鏈用來設置一套配置(對流來說這就是一箇中間操作鏈),接着是調用built方法(對流來說就是終端操作)。

爲方便起見,表4-1和表4-2總結了你前面在代碼例子中看到的中間流操作和終端流操作。注意這只是總結之前代碼中我們遇到的操作,並不是全部。

圖片

 

圖片

小結

 

  • 流是“從支持數據處理操作的源生成的一系列元素”。

  • 流利用內部迭代:迭代通過filter、map、sorted等操作被抽象掉了。

  • 流操作有兩類:中間操作和終端操作。

  • filter和map等中間操作會返回一個流,並可以鏈接在一起。可以用它們來設置一條流水線,但並不會生成任何結果。

  • forEach和count等終端操作會返回一個非流的值,並處理流水線以返回結果。

  • 流中的元素是按需計算的。

 

作者:翎野君
博客:https://www.cnblogs.com/lingyejun/

 

本篇文章如有幫助到您,請給「翎野君」點個贊,感謝您的支持。

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