Java流中的map算子和flatMap算子的区别

map算子和flatMap算子

map和flatMap都是映射(转换),那么他们之间究竟有什么区别呢?

1.我们先简单了解下map算子:

@org.junit.Test public void test1(){ List<String> words = Arrays.asList("hello","world"); words.stream() .map(String::length) //使用了方法引用,将String类型转换为int类型 .forEach(System.out::println); } //输出:5 5

map是流的中间操作, Stream map(Function<? super T, ? extends R> mapper)

传入一个Function函数式接口,返回一个流。关于函数式接口和lambda表达式可以看我之前的随笔。

2.再看个例子,来简单了解下两者间的区别,先着重思考一下下面的案例用map会有什么问题?

​ 需求:传入一个集合 list = Arrays.asList("hello","Hello")

​ 要求:输出:h,e,l,o,H (单词里面的每一个字母去重 ,并且进行打印)

@org.junit.Test public void test2(){ //错误演示 List<String> list = Arrays.asList("hello","Hello");//h,e,l,o,H list.stream() .map(m->m.split("")) .distinct() .collect(toList()) .stream() .forEach(System.out::println); }

那么输出结果符合我们的需求吗?

//输出结果:这俩行是个什么鬼? [Ljava.lang.String;@51e2adc7 [Ljava.lang.String;@1a8a8f7c

这显然不符合我们的要求,那究竟是哪里出错了呢?我们一步一步分析一下:

1.Stream baseRDD = list.stream(); 将集合转换为流

2.Stream<String[]> mapRDD= baseRDD.map(w->w.split("")); 调用map算子,转换

3.Stream<String[]> distinctRDD= mapRDD.distinct(); 调用distinct算子,去重

4.List<String[]> collectRDD = distinctRDD.collect(toList()); 流转换为集合,最后输出

我们一步一步分析下来,看起来是不是还是没问题呢?接下来让我们再改写一下:

@org.junit.Test public void test3(){ List<String> words = Arrays.asList("hello","Hello");//h,e,l,o,H Stream<String[]> mapRDD = words.stream() .map(word->word.split("")); mapRDD.map(Arrays::stream) .distinct() .collect(toList()) .stream() .forEach(System.out::println); } //输出:这又是个什么鬼???是不是越来越迷糊了,不要着急 java.util.stream.ReferencePipeline$Head@2353b3e6 java.util.stream.ReferencePipeline$Head@631330c

再来一步一步分析一下:

Stream<String[]> map1RDD = words.stream().map(word->word.split("")); 转换

Stream<Stream> map2RDD = map1RDD.map(d->Arrays.stream(d));

Stream<Stream> distinctRDD = map2RDD.distinct();

List<Stream> finalList = distinctRDD.collect(toList());

这里我们需要注意的是:map转化(输入一个类型,返回另外一个类型)

​ 输入类型的值(值的类型是上一个数据集的泛型)

​ 输出数据的类型会作为下一个数据集的泛型

还是不理解?没关系,等会我们通过图来深刻理解一下。

那flatMap算子呢?

@org.junit.Test public void test4(){ List<String> words = Arrays.asList("hello","Hello");//h,e,l,o,H words.stream() .map(word->word.split("")) .flatMap(d->{ Stream<String> stream = Arrays.stream(d); return Arrays.stream(d); }) .distinct() .forEach(System.out::println); } //输出 heloH

居然成功实现了需求,这两者究竟有什么区别呢?我们通过图画来更加生动形象的了解下(画图不易,值得一赞)

Java流中的map算子和flatMap算子的区别

对比一下flatMap算子:

Java流中的map算子和flatMap算子的区别

这样就一目了然了!!!

总结一下:

map算子:map返回值类型就是新的数据集的泛型

flatMap算子: flatMap算子返回类型就是新的数据集的类型

最后再看个案例:

​ 需求:输入:【1,2,3】【3,4】

​ 输出:【(1,3),(1,4),(2,3),(2,4),(3,3),(3,4)】

@org.junit.Test public void test7(){ //集合(.stream()) List<Integer> number1 = Arrays.asList(1,2,3); List<Integer> number2 = Arrays.asList(4,5); /** * 倒着推理一下 : * 最终的结果(终端): List<int[]> * 终端操作的上一个操作:Stream<int[]> * */ List<int[]> pairs = number1.stream() .flatMap(i->{ // Stream<int[]> stream = // number2.stream().map(j->new int[]{i,j}); return number2.stream().map(j->new int[]{i,j}); }) .collect(toList()); Stream<int[]> intArrayRDD = pairs.stream(); intArrayRDD.forEach(arr->{ for(int i : arr){ System.out.print(i+" "); } System.out.println(); }); }//OK

至此,map算子和flatMap算子就介绍完毕了!

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzjgpf.html