Java Stream中map和flatMap方法


最近看到一篇講stream語法的文章,學習Javamap()flatMap()方法之間的區別。

雖然看起來這兩種方法都做同樣的事情,都是做的映射操作,但實際上差之毫厘謬以千里。

通過演示Demo中的代碼可以了解map()flatMap()的具體功能差異。

  • 首先來一段簡單的stream語法foreach方法的用法

演示Demo:

        List<String> funs = Arrays.asList("F", "U", "N");
        funs.stream().forEach(x -> output(x));

控制台輸出:

INFO-> 當前用戶:fv,IP:10.60.192.21,工作目錄:/Users/fv/Documents/workspace/fun/,系統編碼格式:UTF-8,系統Mac OS X版本:10.15.7
F
U
N

Process finished with exit code 0

map方法

map()是一個中間操作,這意味着它返回Stream對象。

  • 先來一個簡單

演示Demo:

        List<String> funs = Arrays.asList("F", "U", "N");
        funs.stream().map(x->x+"001").forEach(x->output(x));

控制台輸出:

INFO-> 當前用戶:fv,IP:10.60.192.21,工作目錄:/Users/fv/Documents/workspace/fun/,系統編碼格式:UTF-8,系統Mac OS X版本:10.15.7
INFO-> f
INFO-> u
INFO-> n
INFO-> F001
INFO-> U001
INFO-> N001
java.util.stream.ReferencePipeline$3@27ae2fd0
java.util.stream.ReferencePipeline$3@29176cc1

Process finished with exit code 0

  • 再來一個復雜的

演示Demo:

        List<String> fun1 = Arrays.asList("one", "two", "three");
        List<String> fun2 = Arrays.asList("four", "five", "six");

        List<List<String>> nestedList = Arrays.asList(fun1, fun2);
        nestedList.stream().map(x -> {
            return x.stream().map(a -> a.toUpperCase());
        }).forEach(x -> output(x));
        

控制台輸出:

INFO-> 當前用戶:fv,IP:10.60.192.21,工作目錄:/Users/fv/Documents/workspace/fun/,系統編碼格式:UTF-8,系統Mac OS X版本:10.15.7
INFO-> java.util.stream.ReferencePipeline$3@45018215
INFO-> java.util.stream.ReferencePipeline$3@30b7c004

顯然,在最后一步輸出的時候,x是一個stream的對象,而不是一個list對象。

當我們嘗試從List<List<String>>獲取值進行操作時,map()無法如預期一樣工作,需要進行修改才能從嵌套的List<List<String>>對象獲取字符串值。

如下:

        List<String> fun1 = Arrays.asList("one", "two", "three");
        List<String> fun2 = Arrays.asList("four", "five", "six");

        List<List<String>> nestedList = Arrays.asList(fun1, fun2);
        nestedList.stream().map(x -> {
            return x.stream().map(a -> a.toUpperCase());
        }).forEach(x ->x.forEach(a->output(a)));

控制台輸出:

INFO-> 當前用戶:fv,IP:10.60.192.21,工作目錄:/Users/fv/Documents/workspace/fun/,系統編碼格式:UTF-8,系統Mac OS X版本:10.15.7
INFO-> ONE
INFO-> TWO
INFO-> THREE
INFO-> FOUR
INFO-> FIVE
INFO-> SIX

Process finished with exit code 0

flatMap方法

讓我們在上述代碼中將map()更改為flatMap(),然后查看輸出。

  • 先來一個簡單

演示Demo:

        List<String> fun1 = Arrays.asList("one", "two", "three");
        List<String> fun2 = Arrays.asList("four", "five", "six");
        List<List<String>> nestedList = Arrays.asList(fun1, fun2);
        nestedList.stream().flatMap(x -> x.stream()).map(x->x.toUpperCase()).forEach(x -> output(x));

控制台輸出:

INFO-> 當前用戶:fv,IP:10.60.192.21,工作目錄:/Users/fv/Documents/workspace/fun/,系統編碼格式:UTF-8,系統Mac OS X版本:10.15.7
INFO-> ONE
INFO-> TWO
INFO-> THREE
INFO-> FOUR
INFO-> FIVE
INFO-> SIX

Process finished with exit code 0

相當於在.flatMap(x -> x.stream())這個時候我們把x.stream()返回的stream對象合並成了一個新的stream對象。這一點在Stream類的方法注釋中找到了印證。

		/**
		·····
     * @return the new stream
     */
    <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

Java 8 map()與flatMap()

map()flatMap()方法都可以應用於Stream<T>Optional<T>對象。並且都返回Stream<R>Optional <U>對象。區別在於map()操作為每個輸入值生成一個輸出值,而flatMap()操作為每個輸入值生成任意數量(零個或多個)的輸出值。

flatMap()中,每個輸入始終是一個集合,可以是ListSetMap

map()操作采用一個方法,該方法針對輸入流中的每個值調用,並生成一個結果值,該結果值返回至stream

flatMap()操作采用的功能在概念上消耗一個集合對象並產生任意數量的值。但是在Java中方法返回任意數目的值很麻煩,因為方法只能返回void或一個對象。

演示Demo:

        List<String> fun1 = Arrays.asList("one", "two", "three");
        List<String> fun2 = Arrays.asList("four", "five", "six");
        Stream.of(fun1,fun2).flatMap(List::stream).forEach(Output::output);

控制台輸出:

INFO-> 當前用戶:fv,IP:10.60.192.21,工作目錄:/Users/fv/Documents/workspace/fun/,系統編碼格式:UTF-8,系統Mac OS X版本:10.15.7
INFO-> one
INFO-> two
INFO-> three
INFO-> four
INFO-> five
INFO-> six

Process finished with exit code 0


公眾號FunTester首發,原創分享愛好者,騰訊雲和掘金社區首頁推薦,知乎七級原創作者,歡迎關注、交流,禁止第三方擅自轉載。

FunTester熱文精選


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM