概念:Steam 是Java8 提出的一個新概念,不是輸入輸出的 Stream 流,而是一種用函數(shù)式編程方式在集合類上進行復(fù)雜操作的工具。簡而言之,是以內(nèi)部迭代的方式處理集合數(shù)據(jù)的操作,內(nèi)部迭代可以將更多的控制權(quán)交給集合類。Stream 和 Iterator 的功能類似,只是 Iterator 是以外部迭代的形式處理集合數(shù)據(jù)的操作。
在Java8以前,對集合的操作需要寫出處理的過程,如在集合中篩選出滿足條件的數(shù)據(jù),需要一 一遍歷集合中的每個元素,再把每個元素逐一判斷是否滿足條件,最后將滿足條件的元素保存返回。而Stream 對集合篩選的操作提供了一種更為便捷的操作,只需將實現(xiàn)函數(shù)接口的篩選條件作為參數(shù)傳遞進來,Stream會自行操作并將合適的元素同樣以stream 的方式返回,最后進行接收即可。
2種操作:
1.intermediate operation 中間操作:中間操作的結(jié)果是刻畫、描述了一個Stream,并沒有產(chǎn)生一個新集合,這種操作也叫做惰性求值方法。
2.terminal operation 終止操作:最終會從Stream中得到值。
如何區(qū)分這2種操作呢?可以根據(jù)操作的返回值類型判斷,如果返回值是Stream,則該操作是中間操作,如果返回值是其他值或者為空,則該操作是終止操作。
如下圖的前2個操作是中間操作,只有最后一個操作是終止操作。
可以形象地理解Stream的操作是對一組粗糙的工藝品原型(即對應(yīng)的 Stream 數(shù)據(jù)源)進行加工成顏色統(tǒng)一的工藝品(即最終得到的結(jié)果),第一步篩選出合適的原型(即對應(yīng)Stream的 filter 的方法),第二步將這些篩選出來的原型工藝品上色(對應(yīng)Stream的map方法),第三步取下這些上好色的工藝品(即對應(yīng)Stream的 collect(toList())方法)。在取下工藝品之前進行的操作都是中間操作,可以有多個或者0個中間操作,但每個Stream數(shù)據(jù)源只能有一次終止操作,否則程序會報錯。
常用的 Stream 流操作:
1.collect(toList()) 終止操作
由Stream中的值生成一個List列表,也可用collect(toSet())生成一個Set集合。
例:取 Stream 中每個字符串并放入一個新的列表,
@Test
public void collectToList() {
String[] testStrings = { "java", "react", "angular", "vue" };
List<String> list = Stream.of(testStrings).collect(Collectors.toList());
for (int i = 0, length = list.size(); i < length; i++) {
System.out.println(list.get(i));
}
}
2.map 中間操作
將一種類型的值映射為另一種類型的值,可以將 Stream 中的每個值都映射為一個新的值,最終轉(zhuǎn)換為一個新的 Stream 流。
例:把 Stream 中每個字符串都轉(zhuǎn)換為大寫的形式,
@Test
public void mapTest() {
String[] testStrings = { "java", "react", "angular", "vue" };
List<String> list = Stream.of(testStrings).map(test -> test.toUpperCase()).collect(Collectors.toList());
list.forEach(test -> System.out.println(test));
}
3.filter 中間操作
遍歷并篩選出滿足條件的元素形成一個新的 Stream 流。
例:篩選出以 j 字母開頭的元素個數(shù),此例中的count方法也是終止操作,是為了計算出 Stream 中的元素個數(shù),
@Test
public void filterTest() {
List<String> list = Arrays.asList("java", "react", "angular", "javascript", "vue");
long count = list.stream().filter(p -> p.startsWith("j")).count();
System.out.println(count);
}
4.flatMap 中間操作
可用 Stream 替換值,并將多個 Stream 流合并成一個 Stream 流。
例:將含有一串?dāng)?shù)字的兩個流合并為一個流,
@Test
public void flapMapTest() {
List<Integer> list = (List<Integer>) Stream.of(Arrays.asList(1, 2, 3, 4, 5, 6), Arrays.asList(8, 9, 10, 11, 12))
.flatMap(test -> test.stream()).collect(Collectors.toList());
for (int i = 0, length = list.size(); i < length; i++) {
System.out.println(list.get(i));
}
}
5.max 、min 終止操作
求 Stream 中的最大值、最小值。
例:取出 Stream 中最長的字符串
@Test
public void maxTest() {
String[] testStrings = { "java", "react", "angular", "javascript", "vue" };
Optional<String> max = Stream.of(testStrings).max((p1, p2) -> Integer.compare(p1.length(), p2.length()));
System.out.println(max);
}
6.reduce 終止操作
從 Stream 的一組值中生成另一個值。
例:上述的max、min、count 實際上都是 reduce 操作,求出 Stream 元素數(shù)值的總和,
@Test
public void reduceSumTest() {
int sum = Stream.of(5, 6, 7, 8).reduce(0, (accumulator, element) -> accumulator + element);
System.out.println(sum);
}
reduce方法的第一個參數(shù)值 0 是初始值,第二個lambda表達式參數(shù) (accumulator, element) -> accumulator + element 是執(zhí)行求和操作,其中 accumulator 是累加器,element 是每次迭代的當(dāng)前元素數(shù)值。
注意:Stream 流操作遠不止以上介紹的幾種,這里只介紹流操作的認(rèn)識和幾個簡單實現(xiàn),更多的流操作可查閱 API 官方文檔,靈活結(jié)合 lambda 表達式和 Stream 操作可以更愉快地完成常見的集合操作。
————————————————
版權(quán)聲明:本文為CSDN博主「那些年的國文課」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u014519461/article/details/77940693