面试官:Java 8 map 和 flatMap 的区别?大部分人答不上来!
共 2037字,需浏览 5分钟
·
2022-01-09 11:59
点击关注公众号,Java干货及时送达
来自公众号:Java技术栈
背景
栈长面试会经常问 Java 8 map 和 flatMap 的区别,大部分人都答不上来,会用 map 的都不多,还有一部分人甚至都不知道这两个玩意是干嘛用的,有的还以为我问 HashMap 和 FlatMap。。
这里所问的 map 和 flatMap 并不是集合,它们都是 Stream 流接口中的方法,如果你没用过,我估计在座的各位也有点晕,那么今天栈长就给大家扫个盲,以实际案例来剖析这两个玩意,让你面试的时候再也不怕问了!
如图所示:
在 Java 8 Stream(流)接口中有 8 个特别有意思的方法,其实就是分为两大类:
map flatMap
现在知道这两个玩意的来路了吧?!
其中,xxToXxx 就是转换为不同的类型的流。
map
map 方法的作用:
对流中的每个元素进行转换
比如现在有一个 List
private static List LIST = Arrays.asList("https://", "www", ".", "javastack", ".", "cn");
我想让每个元素后面都加上 "---":
/**
* map 转换
* @author: 栈长
* @from: 公众号Java技术栈
*/
private static void map() {
List mapList = LIST.stream().map(e -> e.concat("---")).collect(Collectors.toList());
mapList.forEach(System.out::print);
System.out.println("\nmap list size: " + mapList.size());
System.out.println();
}
1)先把 List 转换为 Stream;
2)调用 Stream.map 方法对 Stream 中的每个元素再封装操作一遍;
3)把 Stream
输出结果:
=====map list===== https://---www---.---javastack---.---cn--- map list size: 6
结果符合预期。
另外,我将 Java 8知识点我也整理到了小程序,都是面试常考的,大家可以在Java面试库小程序在线刷题。
如果 List 中的元素都是整数型:
private static List NUMBERS_LIST = Arrays.asList("22", "19", "89", "90");
那么就可以 直接使用内置的 mapToXxx 方法,这里以 mapToLong 演示:
/**
* mapToLong 转换
* @author: 栈长
* @from: 公众号Java技术栈
*/
private static void mapToLong() {
System.out.println("=====map to long list=====");
List longList = NUMBERS_LIST.stream().mapToLong(Long::valueOf).boxed().collect(Collectors.toList());
longList.forEach(System.out::println);
System.out.println("map to long list size: " + longList.size());
System.out.println();
}
1)先把 List 转换为 Stream;
2)调用 Stream.mapToLong 方法把流转换为 LongStream 类型;
3)调用 LongStream.boxed 方法收集为 Stream
4)把 Stream
输出结果:
=====map to long list===== 22 19 89 90 map to long list size: 4
当然这个使用 map 也能实现,但使用 mapToXxx 可以将原始流(Stream)转换为 XxxStream:
XxxStream 可以有更多基于整数型的功能,比如快速对元素进行汇总(sum)、求最大数(max)、最小数(min)等等,如果要涉及到元素计算,使用 mapToXxx 会更香。
如源码所示:
Stream map(Function super T, ? extends R> mapper);
LongStream mapToLong(ToLongFunction super T> mapper);
map 和 mapToXxx 的返回类型是不一样的。
本文所有完整示例源代码已经上传:
https://github.com/javastacks/javastack
flatMap
flatMap 方法的作用:
flat 是平铺的意思,flatMap 即对流中每个元素进行平铺后,形成多个流合在一起
比如现在有 3 个字符串数组:
String[] arr1 = {"https://", "www", ".", "javastack", ".", "cn"};
String[] arr2 = {"公众号", ":", "Java技术栈"};
String[] arr3 = {"作者", ":", "栈长"};
现在直接转换为 Stream:
System.out.println("=====arrays list=====");
List list = Stream.of(arr1, arr2, arr3).collect(Collectors.toList());
list.forEach(System.out::print);
System.out.println("\narrays list size: " + list.size());
System.out.println();
结果输出:
=====arrays list===== [Ljava.lang.String;@21b8d17c[Ljava.lang.String;@6433a2[Ljava.lang.String;@5910e440 arrays list size: 3
没错,是 3 个数组元素。
再来看使用 flatMap 方法的效果:
System.out.println("=====flatmap list=====");
List mapList = list.stream().flatMap(Arrays::stream).collect(Collectors.toList());
mapList.forEach(System.out::print);
System.out.println("\nflatmap list size: " + mapList.size());
System.out.println();
结果输出:
=====flatmap list===== https://www.javastack.cn公众号:Java技术栈作者:栈长 flatmap list size: 12
元素大小变成了 12,把 3 个数组流中的元素全部平铺合到一个流中了,然后流中总共为 12 个元素。
这里我用的数组类型,如果是多个 List
总结
map 是对流元素进行转换,flatMap 是对流中的元素(数组)进行平铺后合并,即对流中的每个元素平铺后又转换成为了 Stream 流。
来看下两个方法的源码:
Stream map(Function super T, ? extends R> mapper);
Stream flatMap(Function super T, ? extends Stream extends R>> mapper);
其参数是不一样的,map 前、后的每个元素都是 R 类型,flatMap 前、后的每个元素由原来的 R 类型都变成了 Stream 类型。
再小小总结下:
map 适用于对每个元素进行简单的转换,flatMap 适用于对数组流进行平铺后合并,两个方法的应用场景不一样。
所以,你学废了吗?赶紧用在项目中吧,提升自己的硬实力,让同事对你刮目相看!
本文所有完整示例源代码已经上传:
https://github.com/javastacks/javastack
欢迎 Star 学习,后面 Java 示例都会在这上面提供!