Stream中map和flatMap差异分析
Java8的Stream中引入了对流的各种计算方法,其中map和flatMap的区别常常把人搞的晕头转向,本文对此进行分析。
定义的区别
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
相同点
- 参数类型相同:都是一个
Function,使用该参数对流中的元素进行转换 - 返回值类型相同:都是一个流对象
Stream<R>
不同点
Function中的转换结果不同:map为返回流中的元素R,flatMap为一个继承了Stream<? extends R>类型,即它是一个Stream- 也就是说,
map中Function返回的R会原封不动的放入流中,不管它是什么类型;而flatMap中Function返回的Stream<R>会被拆开放入到结果流中例子
OK,我们来看一个例子,假设我们有一个字符串数组:
String[] strings = {"Hello World", "你 好 世 界"};如何得到一个Stream对象它的每一个元素是一个单词?
非扁平化
使用
map:Stream<String[]> stream = Arrays.asList(strings).stream(). map(str -> str.split(""));这里
map返回的流是Stream<String[]>类型的,因为传递给map方法的lambda为每个字符串返回了一个String[]。 继续转换:Stream<Stream<String>> streamStream = stream.map(stringArray -> Arrays.stream(stringArray));这里
map又将String[]转化为了Stream<String>最后得到的是Stream<Stream<String>>类型流。
通过上面两个例子可以看出, map 的返回结果流的类型就是直接将转化结果放了进去,如果转换结果是集合或者数组,那么它不会帮你拆解,或者说扁平化。
扁平化
使用flatMap:
Stream<String[]> stream1 = Arrays.asList(strings).stream().
map(str -> str.split(""));
Stream<String> stringStream = stream1.flatMap(stringArray -> Arrays.stream(stringArray));
可见, flapMap 的转换函数虽然也是生成了一个 Stream<String> ,但是它内部会将这些流进行 扁平化 ,最终返回的是 Stream<String> ,
而不是 Stream<Stream<String>> 。
对什么数据进行了 扁平化 ?是对Stream内部元素为「数组」的Stream流对象。
扁平化 的结果是什么?得到一个新的Stream流对象,它的内部元素为原流对象中元素(数组)中的子元素。
本文首次发布于 StuartLau’s Blog, 转载请保留原文链接.
RedNote
Douban