Java8 常用的Stream流操作

概念: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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容