Java 9 Stream API 新增功能
本文聚焦Java 9 Stream API 新增功能。
1. Stream Takewhile/Dropwhile
假如我們需要生成字符串流,增加一個字符至前一個流的值,直到流當前值的長度小於10.
在java8中如何實現?需要使用短路的中間操作如,limit,allMatch(實際上用於其他目的)。或者基於Spliterator實現自己的takeWhile。總之,把簡單問題複雜化。
Java9的實現非常簡單:
Stream<String> stream = Stream.iterate("", s -> s + "s")
.takeWhile(s -> s.length() < 10);
takeWhile操作帶一個Predicate參數,其應用於元素決定在所有元素中取最長的前綴(如果流是有序的),或者流所有元素的子集(流是無序的)。
繼續學習之前最好理解“最長的前綴”和“流的子集”是什麼意思:
-
最長的前綴:匹配條件的流中連續元素序列. 序列的第一個元素是流的第一個元素, 緊接在序列最後一個元素後面的元素與給定的謂詞不匹配。
-
“流的子集:流中匹配條件的部分元素集合。
介紹完這些關鍵術語後,我們可以較容易地理解另一個新的dropWhile操作。
它恰好是takeWhile的相反操作,如果流是有序的,dropWhile返回的流,是刪除了最長前綴後留下元素集合。如果流是無序的,dropWhile返回的流包括刪除匹配條件的子集後留下元素的集合。
使用前綴獲得流實現丟棄前五個元素:
stream.dropWhile(s -> !s.contains("sssss"));
簡言之,dropWhile操作刪除對於給定條件返回true的元素,並第一次遇到條件返回false停止刪除。
2. Stream Iterate
接着介紹新特性是重載iterate方法實現有限流生成。不要與另一個重載static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
方法混淆,其返回有函數生成的無限順序序列流。
新的iterate增加了一個predicate決定生成流什麼條件必須終止,其使用很方便、簡潔:
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);
}
3. Stream Ofnullable
有時添加至流中的元素可能爲null,我們並不希望這樣值存在流中。因此需要些if條件語句或三元運算符檢查元素是否爲null。
假如我們有collection 和 map 變量,內容如下:
List<String> collection = Arrays.asList("A", "B", "C");
Map<String, Integer> map = new HashMap<>() {
{
put("A", 10);
put("C", 30);
}
};
請看下面示例:
collection.stream()
.flatMap(s -> {
Integer temp = map.get(s);
return temp != null ? Stream.of(temp) : Stream.empty();
})
.collect(Collectors.toList());
這裏需要判斷temp是否爲null,導致flatMap方法過於冗長。爲了避免使用Stream類的ofNullable方法,相同功能代碼非常簡潔:
collection.stream()
.flatMap(s -> Stream.ofNullable(map.get(s)))
.collect(Collectors.toList());
4. 總結
本文介紹了Java 9 Stream Api中新增的方法,這些增強功能會幫助使用更少的代碼實現強大功能。