• 面试官:Java 8 map 和 flatMap 的区别?大部分人答不上来!


    背景

    栈长面试会经常问 Java 8 map 和 flatMap 的区别,大部分人都答不上来,会用 map 的都不多,还有一部分人甚至都不知道这两个玩意是干嘛用的,有的还以为我问 HashMap 和 FlatMap。。

    这里所问的 map 和 flatMap 并不是集合,它们都是 Stream 流接口中的方法,如果你没用过,我估计在座的各位也有点晕,那么今天栈长就给大家扫个盲,以实际案例来剖析这两个玩意,让你面试的时候再也不怕问了!

    如图所示:

    在 Java 8 Stream(流)接口中有 8 个特别有意思的方法,其实就是分为两大类:

    • map
    • flatMap

    现在知道这两个玩意的来路了吧?!

    其中,xxToXxx 就是转换为不同的类型的流。另外,Stream 系列我之前写过一个专题了,这里不再展开,不懂的关注公众号Java技术栈,然后在公众号 Java 教程菜单中阅读。

    map

    map 方法的作用:

    对流中的每个元素进行转换

    比如现在有一个 List<String> 集合:

    private static List<String> LIST = Arrays.asList("https://", "www", ".", "javastack", ".", "cn");
    

    我想让每个元素后面都加上 "---":

    /**
     * map 转换
     * @author: 栈长
     * @from: 公众号Java技术栈
     */
    private static void map() {
        List<String> 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<Stream> 转换为 List;

    输出结果:

    =map list=
    https://---www---.---javastack---.---cn---
    map list size: 6

    结果符合预期。

    另外,我将 Java 8知识点我也整理到了小程序,都是面试常考的,大家可以在Java面试库小程序在线刷题。


    如果 List 中的元素都是整数型:

    private static List<String> 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<Long> 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<Long> 类型;

    4)把 Stream<Long> 转换为 List;

    输出结果:

    =map to long list=
    22
    19
    89
    90
    map to long list size: 4

    当然这个使用 map 也能实现,但使用 mapToXxx 可以将原始流(Stream)转换为 XxxStream:

    XxxStream 可以有更多基于整数型的功能,比如快速对元素进行汇总(sum)、求最大数(max)、最小数(min)等等,如果要涉及到元素计算,使用 mapToXxx 会更香。

    如源码所示:

    <R> Stream<R> 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<String[]> 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<String> 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<String> 类型也是可以的,其底层也是数组,只要能将元素转换成流都是可以的。

    总结

    map 是对流元素进行转换,flatMap 是对流中的元素(数组)进行平铺后合并,即对流中的每个元素平铺后又转换成为了 Stream 流。

    来看下两个方法的源码:

    <R> Stream<R> map(Function<? super T, ? extends R> mapper);<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
    

    其参数是不一样的,map 前、后的每个元素都是 R 类型,flatMap 前、后的每个元素由原来的 R 类型都变成了 Stream 类型。

    再小小总结下:

    map 适用于对每个元素进行简单的转换,flatMap 适用于对数组流进行平铺后合并,两个方法的应用场景不一样。

    所以,你学废了吗?赶紧用在项目中吧,提升自己的硬实力,让同事对你刮目相看!再啰嗦一句,对 Java 8 新增的知识点还不会用的可以关注公众号:Java技术栈,在后台回复:java,Java 8+ 系列教程我都写了一堆了。

    本文所有完整示例源代码已经上传:

    https://github.com/javastacks/javastack

    欢迎 Star 学习,后面 Java 示例都会在这上面提供!

    好了,今天的分享就到这里了,后面栈长会分享更多好玩的 Java 技术和最新的技术资讯,关注公众号Java技术栈第一时间推送,我也将主流 Java 面试题和参考答案都整理好了,在公众号后台回复关键字 "面试" 进行刷题。

    最后,觉得我的文章对你用收获的话,动动小手,给个在看、转发,原创不易,栈长需要你的鼓励。

    版权声明: 本文系公众号 "Java技术栈" 原创,原创实属不易,转载、引用本文内容请注明出处,抄袭者一律举报+投诉,并保留追究其法律责任的权利。

    近期热文推荐:

    1.1,000+ 道 Java面试题及答案整理(2021最新版)

    2.别在再满屏的 if/ else 了,试试策略模式,真香!!

    3.卧槽!Java 中的 xx ≠ null 是什么新语法?

    4.Spring Boot 2.6 正式发布,一大波新特性。。

    5.《Java开发手册(嵩山版)》最新发布,速速下载!

    觉得不错,别忘了随手点赞+转发哦!

  • 相关阅读:
    ORACLE之ora01722和ORA01403的错误测试
    数据库事务的简单学习(一)
    oracle在线重定义(一)
    数据库拆表拆库的常用策略和PL/SQL代码经验谈(zt)
    如何杀掉Oracle的Session
    异步电机参数辨识
    如何下载专利
    电涡流测功机
    Matlab/Simulink 环境下的车用永磁电机系统仿真
    基本放大器电路,希望对各位有用。[转]
  • 原文地址:https://www.cnblogs.com/javastack/p/15598040.html
Copyright © 2020-2023  润新知