Java8通過Stream處理數據(三)

編程語言 Java Numbers 就是愛體驗 2017-05-03

今天我們來看看流操作:利用流處理數據,都是我們平時使用集合時的常用操作,希望對大家有用,

java.util.stream.Stream中的Stream接口定義了許多操作,它們可以分為兩類。在圖1所示的示例中,您可以看到以下操作:

  • filter, sorted, and map 這些可以連接在一起以形成管道

  • collect,關閉管道並返回結果

我們把可以連接的流操作稱為中間操作。它們可以連接在一起,因為它們的返回類型是Stream。關閉流管道的操作稱為終端操作。它們從一個管道產生一個結果,例如List,Integer,甚至是void(任何非Stream類型)。

你可能會想知道為什麼這個區別是重要的。那麼,在流管道上調用終端操作之前,中間操作不執行任何處理;它們是“懶惰的”,這是因為中間操作通常可以通過終端操作“合併”並被處理成一個單一的過程。

Java8通過Stream處理數據(三)

清單6

例如,考慮清單6中的代碼,它從給定的數字列表中計算出兩個偶數的數字。您可能會驚訝於它打印以下內容:

Java8通過Stream處理數據(三)

這是因為limit(2)使用short-circuiting;我們只需要處理流的一部分,而不是所有的流,以返回結果。這與計算使用and運算符鏈接的大型布爾表達式類似:只要一個表達式返回false,我們可以推斷整個表達式是假的,而不計算它。這裡,操作limit返回大小為2的流。

此外,操作filter 和map 已經合併在同一個通行證中。

總結一下我們迄今為止所學到的東西,一般來說,使用流程涉及三件事情:

  • 用於執行查詢的數據源(如集合)

  • 一連串的中間操作,形成一條流管道

  • 一個終端操作,其執行流管線併產生結果

現在我們來瀏覽一些關於流的操作。有關更多示例,請參閱完整列表的java.util .stream.Stream接口以及本文末尾的資源。

過濾。有幾個操作可以用來從流中過濾元素:

  • filter(Predicate):使用謂詞(java.util.function.Predicate)作為參數,並返回包含與給定謂詞匹配的所有元素的流

  • distinct:返回具有唯一元素的流(根據流元素的equals的實現)

  • limit(n):返回不超過給定大小n的流

  • skip(n):返回一個丟棄前n個元素的流

查找和匹配。常見的數據處理模式是確定某些元素是否匹配給定的屬性。您可以使用anyMatch,allMatch和noneMatch操作來幫助您執行此操作。它們都以謂詞作為參數,並返回一個布爾值作為結果(因此,它們是終端操作)。例如,您可以使用allMatch來檢查事務流中的所有元素的值是否高於100,如清單7所示。

Java8通過Stream處理數據(三)

清單 7

此外,Stream接口提供了操作findFirst和findAny,用於從流中檢索任意元素。它們可以與其他流操作(如過濾器)結合使用。 findFirst和findAny都返回一個可選對象,如清單8所示。

Java8通過Stream處理數據(三)

清單8

Optional<T>類(java.util .Optional)是一個容器類,用於表示值的存在或不存在。在清單8中,findAny可能沒有找到任何類型雜貨的交易。可選類包含幾種方法來測試元素的存在。例如,如果一個交易存在,我們可以選擇使用ifPresent方法對可選對象應用一個操作,如清單9所示(我們只打印交易)。

Java8通過Stream處理數據(三)

清單9

映射。 Streams支持方法映射,它將一個函數(java.util.function.Function)作為參數將流的元素投影到另一個表單中。該函數應用於每個元素,“映射”為新元素。

例如,您可能希望使用它從流的每個元素中提取信息。在清單10的示例中,我們從列表中返回每個單詞的長度列表。

Reducing。到目前為止,我們看到的終端操作返回一個布爾值(allMatch等等),void(forEach)或可選對象(findAny等)。我們也一直使用collect將Stream中的所有元素組合成列表。

Java8通過Stream處理數據(三)

清單10

但是,您還可以將流中的所有元素組合以制定更復雜的進程查詢,例如“具有最高ID的交易是什麼?”或“計算所有交易值的總和”。可以使用reduce對流進行操作,其重複地對每個元素應用操作(例如,添加兩個數字),直到產生結果。它通常被稱為功能編程中的摺疊操作,因為您可以將此操作視為“摺疊”一張長紙(流),直到形成一個小方形,這是摺疊操作的結果。

它有助於首先看看我們如何使用for循環計算列表的總和:

Java8通過Stream處理數據(三)

使用加法運算符迭代地組合數字列表中的每個元素以產生結果。我們基本上將“數字”列表“減少”為一個數字。此代碼中有兩個參數:sum變量的初始值,在這種情況下為0,以及組合列表的所有元素的操作,在本例中為+

在流上使用reduce方法,我們可以總結流的所有元素,如清單11所示。reduce方法有兩個參數:

int sum = numbers.stream().reduce(0, (a, b) -> a + b);

清單11

  • 一個初始值,這裡是0

  • 一個二進制操作符<T>組合兩個元素併產生一個

reduce方法基本上是抽象重複應用的模式。諸如“計算產品”或“計算最大值”的其他查詢(見清單12)成為reduce方法的特殊用例。

Java8通過Stream處理數據(三)

清單12

數字流

您剛看到可以使用reduce方法來計算整數流的總和。但是,有一個成本:我們執行許多包裝操作,以反覆添加Integer對象在一起。如果我們可以調用一個sum方法,如清單13所示,是否更清楚我們的代碼的意圖呢?

Java8通過Stream處理數據(三)

清單13

Java SE 8引入了三個原始的專用流接口來解決這個問題,即IntStream,DoubleStream和LongStream,它們分別將流的元素專門化為int,double和long。

您將用於將流轉換為專門版本的最常用的方法是mapToInt,mapToDouble和mapToLong。這些方法類似於我們之前看到的方法映射,但是它們返回一個專門的流而不是Stream <T>。例如,我們可以改進清單13中的代碼,如清單14所示。您還可以使用包裝操作將原始流轉換為對象流。

Java8通過Stream處理數據(三)

清單14

最後,另一種有用的數字流形式是數字範圍。例如,您可能希望生成1到100之間的所有數字。Java SE 8引入了IntStream,DoubleStream和LongStream兩種可用的靜態方法,以幫助生成範圍和範圍關閉。

兩種方法都將起始值作為第一個參數,範圍的結束值作為第二個參數。然而,range是排他的,而rangeClosed是包容性的。清單15是使用rangeClosed返回10到30之間的所有奇數數據流的示例。

Java8通過Stream處理數據(三)

清單15

創建流

有幾種方法來構建流。您已經看到了如何從集合中獲取流。而且,我們玩數字流。您還可以從值,數組或文件創建流。另外,甚至可以從一個函數生成一個流來產生無限流!

從值或數組創建流是直截了當的:只需使用靜態方法Stream .of的值和數組的Arrays.stream,如清單16所示。

Java8通過Stream處理數據(三)

清單16

您也可以使用Files.lines靜態方法轉換文本流中的文件。例如,在清單17中,我們計算文件中的行數。

Java8通過Stream處理數據(三)

清單17

無限流。最後,在我們結束關於流的第一篇文章之前,這是一個令人興奮的想法。現在你應該明白,流的要素是按需生產的。有兩種靜態方法 -Stream.iterate和Stream .generate - 可以讓你從一個函數創建一個流。然而,因為元素是按需計算的,這兩個操作可以產生“永遠”的元素。這就是我們所說的無限流:一個沒有固定大小的流,當我們從一個固定的採集。

清單18是一個使用iterate來創建所有數字的流的示例,它是10的倍數。迭代方法採用一個初始值(這裡為0)和一個lambda(類型為UnaryOperator <T>)來連續應用於每個新的產值。

Stream<Integer> numbers = Stream.iterate(0, n -> n + 10);

清單18

我們可以使用限制操作將無限流轉換為固定大小的流。例如,我們可以將流的大小限制為5,如清單19所示。

numbers.limit(5).forEach(System.out::println); // 0, 10, 20, 30, 40

清單19

結論 Java SE 8引入了Streams API,它可以讓您表達複雜的數據處理查詢。在本文中,您已經看到一個流支持許多操作,例如filter, map, reduce, 和 iterate,可以組合起來寫入簡潔明瞭的數據處理查詢。這種編寫代碼的新方法與在Java SE 8之前如何處理集合非常不同。但是它具有許多好處。首先,Streams API使用諸如laziness 和 short-circuiting的幾種技術來優化您的數據處理查詢。第二,流可以自動並行化以利用多核架構。在本系列的下一篇文章中,我們將探討更多高級操作,如flatMap和collect。敬請關注。

相關推薦

推薦中...