map 操作算是比较常用的操作了,它可以将元素经过处理后输出成另一个元素。这就和 java method 很像了,输入参数,经过方法处理,输出一个返回参数。
map
方法定义
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
map 方法看起来就很简洁明了,入参是 Function,作用是将元素 T 经过逻辑处理后转换成 R。当然,这个转换过程中可做的东西就多了。比如类型转换、属性提取、逻辑运算、业务处理等。
使用举例
1 | public void mapTest() { |
运行后输出如下:
[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,这样才更容易对比理解。
先给定初始字符串数组:
1 | String[] strs = {"this", "is", "flatmap"}; |
- 将三个字符串后加上空格依次打印
1 | Arrays.stream(strs).map(str -> str + " ").forEach(System.out::print); |
此时,对于三个元素,是转换成了另一个字符串
- 将所有字母依次输出
一般思路是将这三个字符串分割成单个字母进行输出,我们尝试一下下面的代码
1 | 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),把数组里的元素压出来。
1 | Arrays.stream(strs).map(str -> str.split("")).flatMap(Arrays::stream).forEach(System.out::print); |
此时,输出的就是 thisisflatmap 了。
当然,了解了 flatmap,也可以这样写。
1 | 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
