Stream
Java 8 中一個(gè)主要的新功能是引入了流(Stream)功能。在java.util.stream
中包含用于處理元素序列的類。其中,最重要的類是Stream<T>
。下面我們就來(lái)看看如何使用現(xiàn)有的數(shù)據(jù)源創(chuàng)建流。
創(chuàng)建Stream
可以使用 stream()
和 of()
方法從不同的數(shù)據(jù)源(例如:集合、數(shù)組)創(chuàng)建流:
String[] arr = new String[]{"萬(wàn)", "貓", "學(xué)", "社"};
Stream<String> stream = Arrays.stream(arr);
stream = Stream.of("萬(wàn)", "貓", "學(xué)", "社");
Collection
接口新增了一個(gè) stream()
默認(rèn)方法,允許使用任何集合作為數(shù)據(jù)源來(lái)創(chuàng)建 Stream<T>
:
List<String> list = new ArrayList();
list.add("萬(wàn)");
list.add("貓");
list.add("學(xué)");
list.add("社");
Stream<String> stream = list.stream();
在多線程中使用Stream
Stream 還通過(guò)提供 parallelStream()
方法來(lái)簡(jiǎn)化多線程操作,該方法以并行模式運(yùn)行對(duì)流元素的操作。
下面的代碼可以對(duì)流的每個(gè)元素并行運(yùn)行 doWork()
方法:
List<String> list = new ArrayList();
list.add("萬(wàn)");
list.add("貓");
list.add("學(xué)");
list.add("社");
list.parallelStream().forEach(element -> doWork(element));
接下來(lái),我們將介紹一些基本的 Stream 操作。
Stream 操作
在流上可以執(zhí)行許多有用的操作。它們被分為中間操作(返回 Stream<T>
)和終端操作(返回明確定義類型的結(jié)果),中間操作允許鏈接。
我需要注意的是,流上的操作不會(huì)改變數(shù)據(jù)源。
下面是一個(gè)簡(jiǎn)單的例子:
List<String> list = new ArrayList();
list.add("萬(wàn)");
list.add("貓");
list.add("學(xué)");
list.add("社");
long count = list.stream().distinct().count();
在上面的例子中,distinct()
方法表示一個(gè)中間操作,它創(chuàng)建了前一個(gè)流的唯一元素的新流。而 count()
方法是一個(gè)終端操作,它返回流的大小。
迭代
Stream 幫助我們替代了 for、for-each 和 while 循環(huán)。它可以讓我們把精力集中在操作的邏輯上,而不是在迭代元素序列上。
比如下面的代碼:
for (String string : list) {
if (string.contains("貓")) {
return true;
}
}
這段代碼只需要一行 Stream 代碼就可以實(shí)現(xiàn):
boolean isExist = list.stream().anyMatch(element -> element.contains("貓"));
過(guò)濾
filter()
方法可以讓我們選擇滿足謂詞條件的元素流。
比如下面的代碼:
List<String> list = new ArrayList();
list.add("萬(wàn)");
list.add("貓");
list.add("學(xué)");
list.add("社");
Stream<String> stream = list.stream().filter(element -> element.contains("貓"));
在上面的例子中,創(chuàng)建了一個(gè) List<String>
的 Stream<String>
,查找該流中所有包含字符“貓”的元素,并創(chuàng)建一個(gè)只包含篩選后元素的新流。
映射
為了通過(guò)將特殊函數(shù)應(yīng)用于流元素來(lái)轉(zhuǎn)換它們,并將這些新元素收集到流中,我們可以使用 map()
方法。
比如下面的代碼:
List<String> list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
Stream<Integer> stream = list.stream().map(str -> Integer.valueOf(str));
在上面的例子中,通過(guò)對(duì)初始流的每個(gè)元素應(yīng)用特定的 lambda 表達(dá)式將 Stream<String>
轉(zhuǎn)換為 Stream<Integer>
。
如果您有一個(gè)流,其中每個(gè)元素都包含其自己的元素序列,并且您想創(chuàng)建這些內(nèi)部元素的流,則應(yīng)使用 flatMap()
方法。
比如下面的代碼:
public class Writer {
private String name;
private List<String> books;
}
List<Writer> writers = new ArrayList<>();
writers.add(new Writer());
Stream<String> stream = writers.stream().flatMap(writer -> writer.getBooks().stream());
在上面的例子中,我們有一個(gè)類型為 Writer
的元素列表。Writer
類包含一個(gè)類型為 List<String>
的字段 books
。使用 flatMap() 方法,字段 books
中的每個(gè)元素將被提取并添加到新的結(jié)果流中。之后,最開始的 Stream 將會(huì)丟失。
匹配
Stream 提供了一組方便的工具,根據(jù)一些謂詞驗(yàn)證一個(gè)序列的元素。我們可以使用以下方法之一:
-
anyMatch()
:只要有一個(gè)條件滿足即返回true -
allMatch()
:必須全部都滿足才會(huì)返回true -
noneMatch()
:全都不滿足才會(huì)返回true
它們都返回 boolean 的終端操作。
比如下面的代碼:
List<String> list = new ArrayList();
list.add("萬(wàn)");
list.add("貓");
list.add("學(xué)");
list.add("社");
list.stream().anyMatch(element -> element.contains("萬(wàn)")); // true
list.stream().allMatch(element -> element.contains("萬(wàn)")); // false
list.stream().noneMatch(element -> element.contains("萬(wàn)")); // false
對(duì)于空的 Stream,無(wú)論給定的謂詞是什么,allMatch() 方法都將返回 true:
Stream.empty().anyMatch(Objects::nonNull); // false
這是一個(gè)合理的值,因?yàn)槲覀冋也坏讲粷M足謂詞的任何元素。
同樣地,對(duì)于空的 Stream,anyMatch() 方法總是返回 false:
Stream.empty().anyMatch(Objects::nonNull); // false
同樣地,這也是合理的,因?yàn)槲覀冋也坏綕M足這個(gè)條件的元素。
合并
我可以使用類型為 Stream 的 reduce()
方法,根據(jù)指定的函數(shù)將一系列元素合并為某個(gè)值。這個(gè)方法有兩個(gè)參數(shù):第一個(gè)是起始值,第二個(gè)是累加器函數(shù)。
比如下面的代碼:
List<Integer> integers = Arrays.asList(1, 2, 3);
Integer reduced = integers.stream().reduce(4, (a, b) -> a + b);
在上面的例子中,有一個(gè) List<Integer>
,我們將這些元素加起來(lái),并加上一個(gè)初始的整數(shù)(在這個(gè)例子中是4)。那么,運(yùn)行以下代碼的結(jié)果是10(4 + 1 + 2 + 3)。
收集
在 Stream 類型中,也可以通過(guò) collect()
方法來(lái)進(jìn)行收集。這個(gè)操作非常方便,可以將一個(gè)流轉(zhuǎn)換為 Collection
或 Map
,也可以將一個(gè)流表示為單個(gè)字符串。Collectors
是一個(gè)實(shí)用類,提供了幾乎所有典型的收集操作的解決方案。對(duì)于一些不太常見(jiàn)的任務(wù),可以創(chuàng)建自定義的收集器。
下面的代碼使用終端操作 collect()
將 Stream<String>
轉(zhuǎn)換為 List<String>
。
List<String> resultList
= list.stream().map(element -> element.toUpperCase()).collect(Collectors.toList());
最后
Stream 的高級(jí)示例非常豐富,本文的目的是為了讓我們快速了解 Stream 功能的用法,并啟發(fā)我們繼續(xù)探索和深入學(xué)習(xí)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-441700.html
Stream 是 Java 8 中非常強(qiáng)大和實(shí)用的 API,它為開發(fā)人員提供了一種更加簡(jiǎn)便的方式來(lái)處理數(shù)據(jù)。希望我們通過(guò)本文的介紹和示例,可以快速上手使用 Stream,并繼續(xù)深入學(xué)習(xí)和探索。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-441700.html
到了這里,關(guān)于使用 Java 8 中的 Stream ,可以讓你寫代碼事半功倍的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!