stream and lambda(9) - 中間操作之map操作(map、flatmap)
map 操作算是比較常用的操作了,它可以將元素經過處理後輸出成另一個元素。這就和 java method
很像了,輸入引數,經過方法處理,輸出一個返回引數。
map
方法定義
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
map
方法看起來就很簡潔明瞭,入參是 Function
,作用是 將元素 T 經過邏輯處理後轉換成 R 。當然,這個轉換過程中可做的東西就多了。比如型別轉換、屬性提取、邏輯運算、業務處理等。
使用舉例
public void mapTest() { Stream<Integer> of = Stream.of(1, 23, 4); List<String> result = of.map(i -> "my value is " + i).collect(Collectors.toList()); System.out.println(result); }
執行後輸出如下:
[my value is 1, my value is 23, my value is 4]
經過 map,我們將一個數字轉成了一大串的字串。(小聲BB,這要是能把我的餘額 map(money -> 100 * money)
該有多好啊)
flatmap
方法定義
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
flatmap
就很容易讓人分不清和 map
的區別了。
首先先從名字上看,壓平了 map
?往死裡給我 map
?
還是從入參上來分析吧。經過 Function
運算,把元素轉化成一個 Stream
。瞭解了,和 map
的區別是, map
是把元素從 A 物件轉換成 B 物件,而 flatmap
是把元素從 A 物件轉換成流。
大致過程如下圖,這樣看你就明白是怎麼 壓平
了的了。
使用舉例
首先,我們還是看下 map
,然後再看 flatmap
,這樣才更容易對比理解。
先給定初始字串陣列:
String[] strs = {"this", "is", "flatmap"};
- 將三個字串後加上空格依次列印
Arrays.stream(strs).map(str -> str + " ").forEach(System.out::print);
此時,對於三個元素,是轉換成了另一個字串
- 將所有字母依次輸出
一般思路是將這三個字串分割成單個字母進行輸出,我們嘗試一下下面的程式碼
Arrays.stream(strs).map(str -> str.split("")).forEach(System.out::print);
此時,我們預期的是輸出 thisisflatmap
,但是實際上輸出的卻是 [Ljava.lang.String;@36b4cef0[Ljava.lang.String;@fad74ee[Ljava.lang.String;@1a1d6a08
。看來,輸出的並不是單個的字母,為什麼呢?
原因就在於, map
之後,字串轉成了陣列,所以輸出了陣列。想要輸出單個字元怎麼辦? 把陣列壓平(flat),把數組裡的元素壓出來 。
Arrays.stream(strs).map(str -> str.split("")).flatMap(Arrays::stream).forEach(System.out::print);
此時,輸出的就是 thisisflatmap
了。
當然,瞭解了 flatmap
,也可以這樣寫。
Arrays.stream(strs).flatMap(str -> Arrays.stream(str.split(""))).forEach(System.out::print);
總結
-
map
的本質就是傳入一個Function
,將單個元素轉成另一個元素,然後將所有元素組成一個新的Stream
。 -
flatmap
的本質是傳入一個Function
,將單個元素轉成一個Stream
,然後將多個Stream
合併成一個新的Stream
。 - 如果還是有些迷糊,請看圖。
注:本文配套程式碼可在 github
檢視: stream-and-lambda
- stream and lambda(18) - 終止操作之 stream 收集器 collectors
- stream and lambda(15) - 終止操作之 stream 陣列操作 toArray
- stream and lambda(13) - 終止操作之計數 count 與比較 min、max
- stream and lambda(12) - 終止操作之查詢與匹配(findAny、findFirst、allMatch、anyMatch、noneMatch)
- stream and lambda(11) - Optional 簡介
- stream and lambda(10) - 中間操作之排序sorted與除錯peek
- stream and lambda(9) - 中間操作之map操作(map、flatmap)
- stream and lambda(8) - 中間操作之篩選操作(filter、distinct、limit、skip)
- stream and lambda(7) - stream 的建立
- stream and lambda(6) - stream 簡介
- stream and lambda(5) - lambda 表示式最佳實踐
- stream and lambda(3) - jdk 提供的函式式介面
- stream and lambda(2) - 函式式介面簡介
- stream and lambda(1) - lambda 簡介