JDK8特性:Stream流操作中的map()与 flatMap()

一、map()与 flatMap() 功能说明,两者的相同点与不同点

1、功能说明

(1)map(),对集合中的元素逐个进行函数操作映射成另外一个。
(2)flatMap,接收一个函数作为参数,将流中的每个值都转换为另一个流,然后把所有的流都连接成一个流。

【示例一】
// 如果我们把List中的 所有字符变为大写。
Map 操作
[['a', 'b', 'c'], ['d', 'e', 'f']]   =>>   [['A', 'B', 'C'], ['D', 'E', 'F']]

FlatMap 操作
[['a', 'b', 'c'], ['d', 'e', 'f']]   =>>   ['A', 'B', 'C', 'D', 'E', 'F']

2、相同点

Map 和 FlatMap,都是流中 集合数据类型的 转换操作符。

3、不同点

(1)Map 是 将 集合数据中每一个元素作为 参数 传入的lambda表达后进行转换操作, 得到的结果用一个ArrayList 收集起来。
(2)FlatMap, Flat(扁平化),顾名思义, 就是在Map的基础上,会将集合的数据结构给展开。flatMap()方法用于将流中的每个元素转换为一个新的流,然后将这些新的流合并成一个流。
(3)FlatMap传入的lambda表达式的返回值,必须为集合接口类型。如:flatMap(Arrays::stream)、flatMap(List::stream)

二、源码分析【待深入学习】

1、map() 源码分析

map是集合接口Iterable的一个扩展函数,它有两个泛型 T和R, T是集合接口容器包裹的元素数据类型,以上面的【示例一】例子就是List, R 是lambda表达式的返回类型,也是map操作后所得到的集合容器装载元素的数据类型,以上面的【示例一】例子就是<List>。
transform是一个lambda表达式,或说函数类型,它的参数类型是T,返回值类型是R,当我们调用了map操作符后,它干了什么呢?它就是直接 将一个 新的ArrayList 和 lambda表达式一并传入mapTo()方法中。
在这里插入图片描述
那么它在mapTo方法中做了什么呢?非常简单,就是遍历一遍 集合, 以上面的例子 遍历的结果就是 [‘a’, ‘b’, ‘c’] 和 [‘d’, ‘e’, ‘f’]两个元素,将这些元素分别执行lambda表达式,将得到的结果用那个 新的ArrayList收集起来。
在这里插入图片描述

2、flatMap() 源码分析

flatMap也是一样的,是集合接口Iterable的一个扩展函数,操作符需要传入一个lambda表达式,不同的是这个lambda表达式的返回值是一个 集合接口类型(list, set等)。它创建了一个新的ArrayList实例,把实例和lambda表达式一并作为参数传入 flatMapTo方法中。
在这里插入图片描述
我们看看flatMapTo干了啥?flatMap先是遍历一遍集合内的元素,将每一个元素按照lambda表达式的逻辑进行处理, 处理后的结果(集合接口类型)将它添加到 新的ArrayList, 注意了,它添加的方式是 addAll(集合接口)。这个方法就自然而然把元素的集合结构给展开了。
在这里插入图片描述

三、代码实践

1、代码

package jdk8;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description  JDK8特性:Stream流操作中的map()与 flatMap()
 **/
public class StreamTest {
    /* 做测试用的数据 */
    private List<Employee> getChineseList(){
        List<Employee> employeeList = Arrays.asList(
                new Employee( "张三", 23),
                new Employee("李四", 25),
                new Employee( "王五", 26),
                new Employee( "赵子龙", 20)
        );
        return employeeList;
    }

    private List<Employee> getBritishList(){
        List<Employee> employeeList = Arrays.asList(
                new Employee( "tom", 23),
                new Employee("lisa", 25),
                new Employee( "alis", 26)
        );
        return employeeList;
    }

    private List<List<Employee>> getAllPeople(){
        List<List<Employee>> allPeople = new ArrayList<>();
        allPeople.add(getChineseList());
        allPeople.add(getBritishList());
        return allPeople;
    }

    /**
     *  验证 map() 方法的基础功能
     */
    private void testMap(){
        System.out.println("验证 map() 方法的基础功能");
        List<Employee> employeeList = getChineseList();
        List<String> nameList = employeeList.stream()
                        .map(employee -> employee.getName())
                        .collect(Collectors.toList());
        System.out.println("           nameList = " + nameList);
    }

    /**
     * 将三维数据,经过两次 flatMap() 方法处理后,变为一维数组
     */
    private void testFlatMap(){
        System.out.println("将三维数据,经过两次 flatMap() 方法处理后,变为一维数组");
        //三维数组
        String [][][] strArrays = {
                {
                        {"a","b"},{"c","d","e"},{"f"}
                },
                {
                        {"g"},{"h"}
                },
                {
                        {"i"}
                }
        };
        List<String> strList = Arrays.stream(strArrays)
                .flatMap(Arrays::stream)
                .flatMap(Arrays::stream)
                .collect(Collectors.toList());
        System.out.println("           strList = " + strList);
    }

    private void testMapOfList(){
        System.out.println("testMapOfList(),经过map()处理后,得到的是一个多维数组");
        List<Employee> employeeList = getChineseList();
        List<List<String>> collect = employeeList.stream()
                            .map(employee -> {
                                    List<String> list = new ArrayList<>();
                                    list.add(employee.getName());
                                    return list;
                                })
                            .collect(Collectors.toList());
        System.out.println("           map() 处理后的 collect = " + collect);
    }

    private void testFlatMapOfList(){
        System.out.println("testFlatMapOfList(),经过flatMap()处理后,得到的是一个一维数组");
        List<Employee> employeeList = getChineseList();
        List<String> collect2 = employeeList.stream()
                            .map(employee -> {
                                List<String> list = new ArrayList<>();
                                list.add(employee.getName());
                                return list;
                            })
                            .flatMap(List::stream)
                            .collect(Collectors.toList());
        System.out.println("           flatMap() 处理后的 collect2 = " + collect2);
    }

    public static void main(String[] args) {
        StreamTest obj = new StreamTest();
        obj.testMap();
        obj.testFlatMap();
        obj.testMapOfList();
        obj.testFlatMapOfList();
    }


}

@Getter
@Setter
@AllArgsConstructor
 class Employee{
    private String name;
    private int age;
 }

2、控制台打印日志

验证 map() 方法的基础功能
           nameList = [张三, 李四, 王五, 赵子龙]
将三维数据,经过两次 flatMap() 方法处理后,变为一维数组
           strList = [a, b, c, d, e, f, g, h, i]
testMapOfList(),经过map()处理后,得到的是一个多维数组
           map() 处理后的 collect = [[张三], [李四], [王五], [赵子龙]]
testFlatMapOfList(),经过flatMap()处理后,得到的是一个一维数组
           flatMap() 处理后的 collect2 = [张三, 李四, 王五, 赵子龙]

【转载说明】本篇博客中的部分内容,转载自以下资源:

1、Map和FlatMap的相同点和区别(作者:黑心的奥利奥)

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值