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

对比一下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算子的区别的更多相关文章
- Python 图像处理 OpenCV (12): Roberts 算子、 Prewitt 算子、 Sobel 算子和 Laplacian 算子边缘检测技术
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- Python 图像处理 OpenCV (13): Scharr 算子和 LOG 算子边缘检测技术
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- Java 8 中的抽象类和接口到底有啥区别?
上一篇栈长发了这篇<Java 8 有多牛逼?打破一切你对接口的认知!>,帮助许多人解开了疑惑,还有读者留言说两者还有啥区别,故引发了此篇: 在我们面试时也会经常遇到面试官问抽象类和接口的区 ...
- Java集合中的Map接口
jdk1.8.0_144 Map是Java三种集合中的一种位于java.util包中,Map作为一个接口存在定义了这种数据结构的一些基础操作,它的最终实现类有很多:HashMap.TreeMap.So ...
- Java集合中的Map接口怎么使用?
Map(双列集合框架) 1.Map接口及实现类概述 Map 接口提供三种collection 视图,允许以键集.值集或键-值映射关系集的形式查看某个映射的内容.映射顺序 定义为迭代器在映射的 coll ...
- 解决 java循环中使用 Map时 在put值时value值被覆盖的问题
其实很简单,只需要把容器换成list 然后在循环中,每次循环末尾map = new HashMap() 或者直接在循环中一开始就实例化hashmap(Map map = new HashMap();) ...
- java 泛型中 T 和 问号(通配符)的区别
类型本来有:简单类型和复杂类型,引入泛型后把复杂类型分的更细了: 现在List<Object>, List<String>是两种不同的类型;且无继承关系: 泛型的好处如: 开始 ...
- Java虚拟机中的栈和堆的定义和区别
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配. 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配 ...
- 灰度图像--图像分割 Sobel算子,Prewitt算子和Scharr算子平滑能力比较
学习DIP第47天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan ,出于尊重文章作者的劳动,转载请标明出处!文章代码已托管,欢迎共同开发: https://g ...
随机推荐
- MySQL5.7主从复制slave报Last_Errno: 1146错误解决
前提:由于slave磁盘未及时扩容原因导致磁盘即将写满,为了不影响业务将slave实例里一个10G的库drop了(项目前期建的库,数据现在已不使用了),然后又drop了master上的该库(对于大库建 ...
- 一劳永逸的解决AFNetworking3.0网络请求问题
AFNetworking在iOS网络请求第三方库中占据着半壁江山,前段时间将AFNetworking进行了3.0版本的迁移,运用面向对象的设计将代码进行封装整合,这篇文章主要为还在寻找AFNetwor ...
- openCryptoki安装
什么是OpenCryptoki OpenCryptoki提供Linux下的PKCS#11库和工具,支持包括TPM和IBM加密硬件以及软件令牌. 目前(2019/05/06)最新release版为3.1 ...
- ES6学习笔记之变量的解构赋值
变量的解构赋值 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构. 数组的解构赋值 以前,为变量赋值,只能直接指定值: 1 2 3 var a = 1; var b = 2; ...
- USB小白学习之路(7) FPGA Communication with PC by CY7C68013,TD_init()解析
注:这个TD_Init()只对EP6进行了配置,将其配置成为Bluk_In端口,而没有对EP2进行配置.这篇文章直接把寄存器的图片贴上来了,看起来比较杂.感兴趣的可以看下一篇文章,是转自CSDN,对E ...
- Java工作流引擎结合可视化表单开发,10分钟完成一个业务流程发布
回忆以前工作流引擎的应用,感觉历历在目啊!当初公司接了一个项目关于政府单位公文流转的管理系统,一开始客户跟我画了十多张业务流程图.话说这十多张业务流程图,涉及的业务范围还蛮多,像用审批授权,开通流程, ...
- 全栈前端入门必看 koa2+mysql+vue+vant 构建简单版移动端博客
koa2+mysql+vue+vant 构建简单版移动端博客 具体内容展示 开始正文 github地址 <br/> 觉得对你有帮助的话,可以star一下^_^必须安装:<br/> ...
- Everything-快速找到你的文件,电脑前的你值得拥有
如果你也是一位电脑使用者,那么你可以考虑下载这个"Everything". Everything是一款非常非常强大的软件.相信不少电脑用户,特别是Windows用户,都尝试使用过W ...
- JavaScript判断一个对象是否为空
本文介绍了判断一个对象是否为空的几种方法 测试用例 test1 = 1; test2 = {}; test3 = {a:1,b:2} 1. 判断Object.keys()的长度 function _i ...
- Spring Boot从入门到精通(七)集成Redis实现Session共享
单点登录(SSO)是指在多个应用系统中,登录用户只需要登录验证一次就可以访问所有相互信任的应用系统,Redis Session共享是实现单点登录的一种方式.本文是通过Spring Boot框架集成Re ...