首页 > 其他分享 >【JDK特性】stream 里面的map和flatMap区别

【JDK特性】stream 里面的map和flatMap区别

时间:2023-02-19 12:44:06浏览次数:53  
标签:map flatMap JDK ArrayList List add Address new

背景

JDK8中, stream流程 下的map 就不多说了,很熟悉,flatmap倒是不是特别熟悉,




map 和 flatMap 的区别

看一个例子:

   List<String> cityListOne = new ArrayList<>();
   cityListOne.add("郑州");
   cityListOne.add("濮阳");
   List<String> cityListTwo = new ArrayList<>();
   cityListTwo.add("廊坊");
   cityListTwo.add("邢台");
   List<String> cityListThree = new ArrayList<>();
   cityListThree.add("大同");
   cityListThree.add("太原");
   List<String> cityListFour = new ArrayList<>();
   cityListFour.add("南昌");
   cityListFour.add("九江");

   Address addressOne = new Address();
   addressOne.setProvince("河南");
   addressOne.setCityList(cityListOne);

   Address addressTwo = new Address();
   addressTwo.setProvince("河北");
   addressTwo.setCityList(cityListTwo);

   Address addressThree = new Address();
   addressThree.setProvince("山西");
   addressThree.setCityList(cityListThree);

   Address addressFour = new Address();
   addressFour.setProvince("江西");
   addressFour.setCityList(cityListFour);

   List<Address> addresses = new ArrayList<>();
   addresses.add(addressOne);
   addresses.add(addressTwo);
   addresses.add(addressThree);
   addresses.add(addressFour);

   //使用map输出所有的城市名称
   addresses.stream()
           .map(address -> address.getCityList())
           .forEach(cityList ->
                   cityList.forEach(city -> System.out.print(city + " "))
           );

   System.out.println("");
   //使用flatMap输出所有城市名称
   addresses.stream()
           .flatMap(address -> address.getCityList().stream())
           .forEach(city -> System.out.print(city + " "));
}


这里可以看到使用 flatMap 也是返回一个 stream流
看到源码也知一二,看到 map 和 flatmap 对于里面的函数式的差异:

@Override
@SuppressWarnings("unchecked")
public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
    Objects.requireNonNull(mapper);
    return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
                                 StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
        @Override
        Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
            return new Sink.ChainedReference<P_OUT, R>(sink) {
                @Override
                public void accept(P_OUT u) {
                    downstream.accept(mapper.apply(u));
                }
            };
        }
    };
}


@Override
public final <R> Stream<R> flatMap(Function<? super P_OUT, ? extends Stream<? extends R>> mapper) {
    Objects.requireNonNull(mapper);
    // We can do better than this, by polling cancellationRequested when stream is infinite
    return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
                                 StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
        @Override
        Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
            return new Sink.ChainedReference<P_OUT, R>(sink) {
                @Override
                public void begin(long size) {
                    downstream.begin(-1);
                }

                @Override
                public void accept(P_OUT u) {
                    try (Stream<? extends R> result = mapper.apply(u)) {
                        // We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
                        if (result != null)
                            result.sequential().forEach(downstream);
                    }
                }
            };
        }
    };
}

嗯,怎么说呢。flalmap 还可以:使用多次

public class User {
    private String name;
    private List<Address> addressList;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Address> getAddressList() {
        return addressList;
    }

    public void setAddressList(List<Address> addressList) {
        this.addressList = addressList;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", addressList=" + addressList +
                '}';
    }
}


// 测试类

public static void main(String[] args) {

    List<String> cityListOne = new ArrayList<>();
    cityListOne.add("郑州");
    cityListOne.add("濮阳");
    List<String> cityListTwo = new ArrayList<>();
    cityListTwo.add("廊坊");
    cityListTwo.add("邢台");
    List<String> cityListThree = new ArrayList<>();
    cityListThree.add("大同");
    cityListThree.add("太原");
    List<String> cityListFour = new ArrayList<>();
    cityListFour.add("南昌");
    cityListFour.add("九江");

    Address addressOne = new Address();
    addressOne.setProvince("河南");
    addressOne.setCityList(cityListOne);

    Address addressTwo = new Address();
    addressTwo.setProvince("河北");
    addressTwo.setCityList(cityListTwo);

    Address addressThree = new Address();
    addressThree.setProvince("山西");
    addressThree.setCityList(cityListThree);

    Address addressFour = new Address();
    addressFour.setProvince("江西");
    addressFour.setCityList(cityListFour);

    List<Address> addresseListOne = new ArrayList<>();
    addresseListOne.add(addressOne);
    addresseListOne.add(addressTwo);
    List<Address> addresseListTwo = new ArrayList<>();
    addresseListTwo.add(addressThree);
    addresseListTwo.add(addressFour);

    //新增用户来包含地址集合
    List<User> userList = new ArrayList<>();
    User u1 = new User();
    u1.setName("张三");
    u1.setAddressList(addresseListOne);

    User u2 = new User();
    u2.setName("李四");
    u2.setAddressList(addresseListTwo);

    userList.add(u1);
    userList.add(u2);



    //使用map输出所有的城市名称
    userList.stream()
            .map(u->u.getAddressList())
            .forEach(addressList->{
                addressList.forEach(address -> {
                    address.getCityList().forEach(city->{
                        System.out.print(city);
                    });
                });
            });

    System.out.println("");//换行
    //使用flatMap输出所有城市名称
    userList.stream()
            .flatMap(u -> u.getAddressList().stream())
            .flatMap(a -> a.getCityList().stream())
            .forEach(city -> System.out.print(city));
}

可以看出flatMap可以使用多次将更深一层的集合流中的数据拿到外层进行处理。而使用map则相当繁琐

就此,如果再遇遍历,可多尝试用一下 flapMap。

完。


参考:
java8中map和flatMap区别 (本文的例子均参考的这里,并且例子说得更好一些)

标签:map,flatMap,JDK,ArrayList,List,add,Address,new
From: https://www.cnblogs.com/aaacarrot/p/17134572.html

相关文章

  • HashMap相关
    底层数据结构,1.7和1.8有什么区别1.7:数组+链表1.8:数组+(链表|红黑树)为什么要用红黑树当链表过长时查询效率太低,树化可以提高查询效率为什么不是一开始就用树,而是达到......
  • JDK、JRE、JVM
    JDK:JavaDevelopmentKit(java开发者工具)JRE:JavaRuntimeEnvironment(java运行时环境)JVM:JAVA VirtualMachine(java虚拟机) ......
  • Linux 安装jdk并配置环境
    1、官网下载安装包注:笔者所用的远程连接工具为WindTerm官网:Oracle官网网盘:网盘下载下拉,找到Java8点击jdk-8u351-linux-x64.tar.gz即可,如果需要登录那就登录一......
  • JDK1.8新特性
    JDK1.8新特性1、Lambda表达式2、::运算符引用方法3、streamStream是JDK1.8新增的一个特性,称之为Stream,它可以给予Lamdba表达式对集合数据进行处理(如:遍历、排序、去重......
  • MapReduce概述
    MapReduce是一种分布式运算程序的编程框架,是用户开发“基于hadoop数据分析应用”的核心框架。核心功能是用户编写的业务逻辑代码和系统自带的组件组合在一起,构成一个分布......
  • linux016之安装JDK
    linux上安装JDK:一:首先检查一下linux上是否已经安装有jdkrpm-qa|grepjdk:查询目前系统已安装的jdk,直接复制该命令执行,如下图就是系统已经安装好的JDK  rpm-qa......
  • Elasticsearch索引优化指南:分片、副本、mapping和analyzer
    Elasticsearch是一个开源的分布式搜索引擎,它的数据存储和查询速度非常快。然而,在面对大规模的数据集和高并发访问时,Elasticsearch的性能也可能受到一些影响。为了最大程度地......
  • Map集合
    介绍 Map在Java⾥边是⼀个接⼝,常⻅的实现类有HashMap、LinkedHashMap、TreeMap和ConcurrentHashMap  内嵌类    Map是java中的接口,Map.Entry是Map的一......
  • Geospatial,Hyperloglog,BitMap
    geospatial:地理位置底层实现geoadd:添加 geopos:获取指定的经纬度 geodist georadius:获取指定位置的指定半径的数据 georadiusbymember:获取指定元素指......
  • 修改linux下jdk环境变量
    1、查看jdk版本:2、查看jdk安装路径:echo$JAVA_HOME    3、用vim/etc/profile进入编辑状态,以下配置需要修改:(配置的jdk的路径一定得对) 修改:JAVA_HOME=/usr......