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

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

对比一下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算子就介绍完毕了!


Java流中的map算子和flatMap算子的区别的更多相关文章

  1. Python 图像处理 OpenCV (12): Roberts 算子、 Prewitt 算子、 Sobel 算子和 Laplacian 算子边缘检测技术

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...

  2. Python 图像处理 OpenCV (13): Scharr 算子和 LOG 算子边缘检测技术

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...

  3. Java 8 中的抽象类和接口到底有啥区别?

    上一篇栈长发了这篇<Java 8 有多牛逼?打破一切你对接口的认知!>,帮助许多人解开了疑惑,还有读者留言说两者还有啥区别,故引发了此篇: 在我们面试时也会经常遇到面试官问抽象类和接口的区 ...

  4. Java集合中的Map接口

    jdk1.8.0_144 Map是Java三种集合中的一种位于java.util包中,Map作为一个接口存在定义了这种数据结构的一些基础操作,它的最终实现类有很多:HashMap.TreeMap.So ...

  5. Java集合中的Map接口怎么使用?

    Map(双列集合框架) 1.Map接口及实现类概述 Map 接口提供三种collection 视图,允许以键集.值集或键-值映射关系集的形式查看某个映射的内容.映射顺序 定义为迭代器在映射的 coll ...

  6. 解决 java循环中使用 Map时 在put值时value值被覆盖的问题

    其实很简单,只需要把容器换成list 然后在循环中,每次循环末尾map = new HashMap() 或者直接在循环中一开始就实例化hashmap(Map map = new HashMap();) ...

  7. java 泛型中 T 和 问号(通配符)的区别

    类型本来有:简单类型和复杂类型,引入泛型后把复杂类型分的更细了: 现在List<Object>, List<String>是两种不同的类型;且无继承关系: 泛型的好处如: 开始 ...

  8. Java虚拟机中的栈和堆的定义和区别

    在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配. 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配 ...

  9. 灰度图像--图像分割 Sobel算子,Prewitt算子和Scharr算子平滑能力比较

    学习DIP第47天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan ,出于尊重文章作者的劳动,转载请标明出处!文章代码已托管,欢迎共同开发: https://g ...

随机推荐

  1. ubuntu16.04安装mysql5.6

    apt-get install software-properties-commonsudo add-apt-repository 'deb http://archive.ubuntu.com/ubu ...

  2. 在没有APP的125年前 印度的外卖小哥是这样送餐

    说到印度,你想到的是什么?咖喱.歌舞剧.开挂的火车?通通不是,我今天要说的是他们的外卖小哥,在印度如同"神"一般的存在.其实印度人不叫这批人为外卖小哥,而称他们为dabbawala ...

  3. iOS开发黑科技之runtime

    iOS 开发之黑科技-runtime runtime其实就是oc底层的一套C语音的API 调用方法的本质就是发消息, 1.动态交换两个方法的实现(特别是交换系统自动的方法) 2.动态添加对象的成员变量 ...

  4. 为什么我们要让人工智能玩游戏:微软Project AIX

    <我的世界>游戏 2016年7月注:Project AIX已正式更名为Project Malmo 注:本文编译自Project AIX: Using Minecraft to build ...

  5. C++扬帆远航——1

    问题及代码: /* * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:test.cpp * 作者:常轩 * 完成日期:2 ...

  6. C++走向远洋——61(项目一、排序函数模板)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  7. C++走向远洋——35(友元,时间)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:time.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  8. 告别ThinkPHP6的异常页面, 让我们来拥抱whoops吧

    春节期间熟悉了TP6, 也写了一个TP6的博客程序,但系统的异常页面实在另外头疼,很多时候无法查看到是哪行代码出的问题. 所以就特别的想把whoops引进来,经过一系列的研究,终于找到了解决的办法: ...

  9. 【Geek议题】合理的VueSPA架构讨论(上)

    前言 web前端发展到现代,已经不再是严格意义上的后端MVC的V层,它越来越向类似客户端开发的方向发展,已独立拥有了自己的MVVM设计模型.前后端的分离也使前端人员拥有更大的自由,可以独立设计客户端部 ...

  10. 大型Java进阶专题(二) 软件架构设计原则(上)

    前言 ​ 今天开始我们专题的第一课了,也是我开始进阶学习的第一天,我们先从经典设计思想开始,看看大牛市如何写代码的,提升技术审美.提高核心竞争力.本章节参考资料书籍<Spring 5核心原理&g ...