Java 8流簡介
1.概述
在本文中,我們將快速瀏覽Java 8添加的主要新功能之一-流。
我們將解釋流的含義,並通過簡單的示例展示流的創建和基本操作。
2.流API
Java 8的主要新功能之一是引入了流功能java.util.stream
,該功能包含用於處理元素序列的類。
中心的API類是[Stream<T>](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html) .
下一節將演示如何使用現有的數據提供者源創建流。
2.1。流創建
可以使用stream()
和of()
方法從不同的元素源(例如集合或數組)創建stream()
:
String[] arr = new String[]{"a", "b", "c"};
Stream<String> stream = Arrays.stream(arr);
stream = Stream.of("a", "b", "c");
將stream()
默認方法添加到Collection
接口,並允許使用任何集合作為元素源來創建Stream<T>
:
Stream<String> stream = list.stream();
2.2。流多線程
Stream API還提供了parallelStream()
方法,該方法以並行模式對流的元素運行操作,從而簡化了多線程處理。
下面的代碼允許為流的每個元素並行運行doWork()
方法:
list.parallelStream().forEach(element -> doWork(element));
在以下部分中,我們將介紹一些基本的Stream API操作。
3.流操作
在流上可以執行許多有用的操作。
它們分為中間操作(返回Stream<T>
)和終端操作(返回確定類型的結果)。中間操作允許鏈接。
還值得注意的是,對流的操作不會更改源。
這是一個簡單的例子:
long count = list.stream().distinct().count();
因此, distinct()
方法表示一個中間操作,該操作創建了先前流的唯一元素的新流。 count()
方法是一個終端操作,
它返回流的大小。
3.1。反復進行
流API有助於替代for
, for-each
,並while
循環。它允許專注於操作的邏輯,但不能專注於元素序列的迭代。例如:
for (String string : list) {
if (string.contains("a")) {
return true;
}
}
只需一行Java 8代碼即可更改此代碼:
boolean isExist = list.stream().anyMatch(element -> element.contains("a"));
3.2。篩選
filter()
方法允許我們選擇滿足謂詞的元素流。
例如,考慮以下列表:
ArrayList<String> list = new ArrayList<>();
list.add("One");
list.add("OneAndOnly");
list.add("Derek");
list.add("Change");
list.add("factory");
list.add("justBefore");
list.add("Italy");
list.add("Italy");
list.add("Thursday");
list.add("");
list.add("");
以下代碼創建List<String>
的Stream<String>
,查找此流中包含char “d”
所有元素,並創建一個僅包含過濾後的元素的新流:
Stream<String> stream = list.stream().filter(element -> element.contains("d"));
3.3。Mapping
為了通過對Stream
元素應用特殊功能來轉換它們並將這些新元素收集到Stream
,我們可以使用map()
方法:
List<String> uris = new ArrayList<>();
uris.add("C:\\My.txt");
Stream<Path> stream = uris.stream().map(uri -> Paths.get(uri));
因此,以上代碼通過將特定的lambda表達式應用於初始Stream
每個元素,將Stream<String>
轉換為Stream<Path>
。
如果您有一個流,其中每個元素都包含其自己的元素序列,並且想要創建這些內部元素的流,則應使用flatMap()
方法:
List<Detail> details = new ArrayList<>();
details.add(new Detail());
Stream<String> stream
= details.stream().flatMap(detail -> detail.getParts().stream());
在這個例子中,我們有一個類型為Detail
的元素列表。 Detail
類包含一個字段PARTS
,它是一個List<String>
。借助flatMap()
方法,將提取字段PARTS
每個元素並將其添加到新的結果流中。之後,初始Stream<Detail>
將丟失.
3.4。匹配
Stream API提供了一組方便的工具來根據某些謂詞驗證序列的元素。為此,可以使用以下方法之一: anyMatch(), allMatch(), noneMatch().
他們的名字是不言自明的。這些是返回boolean
終端操作:
boolean isValid = list.stream().anyMatch(element -> element.contains("h")); // true
boolean isValidOne = list.stream().allMatch(element -> element.contains("h")); // false
boolean isValidTwo = list.stream().noneMatch(element -> element.contains("h")); // false
對於空流,具有任何給定謂詞的allMatch()
方法將返回true
:
Stream.empty().allMatch(Objects::nonNull); // true
這是一個明智的默認值,因為我們找不到任何不滿足謂詞的元素。
同樣, anyMatch()
方法對於空流始終返回false
:
Stream.empty().anyMatch(Objects::nonNull); // false
同樣,這是合理的,因為我們找不到滿足此條件的元素。
3.5。減少
Stream API借助Stream
類型的reduce()
方法,可以根據指定的函數將元素序列減少為某個值。此方法有兩個參數:第一個-起始值,第二個-累加器功能。
假設您有一個List<Integer>
並且希望所有這些元素和一些初始Integer
的總和(在本例中為23)。因此,您可以運行以下代碼,結果將為26(23 +1 + 1 +1)。
List<Integer> integers = Arrays.asList(1, 1, 1);
Integer reduced = integers.stream().reduce(23, (a, b) -> a + b);
3.6。收集中
還可以通過Stream.
類型的collect()
方法來提供減少量Stream.
在將流轉換為Collection
或Map
並以單個字符串形式表示流的情況下,此操作非常方便.
有一個實用程序類Collectors
,可以為幾乎所有典型的收集操作提供解決方案。對於一些並非微不足道的任務,可以創建自定義Collector
。
List<String> resultList
= list.stream().map(element -> element.toUpperCase()).collect(Collectors.toList());
此代碼使用終端的collect()
操作將Stream<String>
簡化為List<String>.
4。結論
在本文中,我們簡要介紹了Java流-絕對是Java 8最有趣的功能之一。
有許多使用Streams的更高級的示例。撰寫本文的目的只是為了快速,實用地介紹您可以使用該功能開始做些什麼,並以此作為探索和進一步學習的起點。
本文隨附的源代碼可在GitHub上獲得。