Java 9 Stream API的改進
1.概述
在本文的快速撰寫中,我們將重點介紹Java 9中新的有趣的Stream API改進。
2.串流收/放
關於這些方法的討論已經在StackOverflow上反復出現(最流行的一種是)。
試想一下,我們要產生一個Stream
的String
中加入一個字符較早前的S Stream
的價值,直到這個電流值的長Stream
低於10
。
我們將如何在Java 8中解決它?我們可以使用一個短路狀的中間業務limit
, allMatch
實際上起到用於其他目的或寫我們自己的takeWhile
實現基於一個Spliterator
,反過來,這樣一個簡單的問題複雜化。
使用Java 9,該解決方案很容易:
Stream<String> stream = Stream.iterate("", s -> s + "s")
.takeWhile(s -> s.length() < 10);
takeWhile
操作採用一個Predicate
,該Predicate
將應用於元素以確定這些元素的最長前綴(如果已排序流)或該流元素的子集(當未排序流時)。
為了前進,我們最好理解“最長前綴”和“ Stream's
子集”這兩個術語Stream's
含義:
- 最長前綴是流中與給定謂詞匹配的元素的連續序列。序列的第一個元素是此流的第一個元素,緊接序列的最後一個元素的元素與給定謂詞不匹配
- 一個
Stream's
子集為一組的一些(但不是全部)元素的Stream
匹配給定的斷言。
在介紹了這些關鍵術語之後,我們可以輕鬆地理解另一個新的dropWhile
操作。
它與takeWhile
恰好相反。如果對流進行排序,則dropWile
在刪除與給定謂詞匹配的元素的最長前綴後,將返回由該Stream
其餘元素組成的Stream
。
否則,如果Stream
是無序的,則dropWile
在刪除與給定謂詞匹配的元素子集之後,將返回由該Stream
其餘元素組成的Stream
。
讓我們使用前面獲得的Stream
丟棄前五個元素:
stream.dropWhile(s -> !s.contains("sssss"));
簡而言之, dropWhile
操作將刪除元素,而元素的給定謂詞返回true
並停止刪除第一個謂詞的false
。
3.流迭代
下一個新功能是用於有限Streams
生成的重載iterate
方法。不要與finite
變體混淆,後者會返回由某個函數生成的無限順序有序Stream
。
一個新的iterate
通過添加一個謂詞來稍微修改此方法,該謂詞適用於確定流何時必須終止的元素。它的用法非常方便和簡潔:
Stream.iterate(0, i -> i < 10, i -> i + 1)
.forEach(System.out::println);
它可以與相應的for
語句關聯:
for (int i = 0; i < 10; ++i) {
System.out.println(i);
}
4.流為空
在某些情況下,我們需要將元素放入Stream
。有時,此元素可以為null
,但我們不希望我們的Stream
包含此類值。它導致編寫if
語句或三元運算符,以檢查元素是否為null.
假設已經成功創建並填充了collection
和map
變量,請看以下示例:
collection.stream()
.flatMap(s -> {
Integer temp = map.get(s);
return temp != null ? Stream.of(temp) : Stream.empty();
})
.collect(Collectors.toList());
為避免此類樣板代碼, ofNullable
方法添加到Stream
類。使用此方法,前面的樣本可以簡單地轉換為:
collection.stream()
.flatMap(s -> Stream.ofNullable(map.get(s)))
.collect(Collectors.toList());
5.結論
我們考慮了Java 9中Stream API的重大更改,以及這些改進如何幫助我們以更少的精力編寫更多有重點的程序。
與往常一樣,可以在Github上找到代碼片段。