Java8 Stream使用flatMap合并List

Java8 Stream使用flatMap合并List之前也写过很多篇关于Java8使用的文章了,但是回顾一下,好像还没介绍过Java8Stream的flatMap操作,昨天刚好在工作中遇到一个场景,发现flatMap简直太方便了,这里总结一下flatMap的常规使用。附带讲一下,使用Java8实现集合的并、交、差操作,其实之前也讲过一种使用Guava的实现方式,具体请参考Guava集合工具 flatMap 首先看一下一种场景,存在一个M…

大家好,又见面了,我是你们的朋友全栈君。

之前也写过很多篇关于Java8使用的文章了,但是回顾一下,好像还没介绍过Java8 Stream的flatMap操作,昨天刚好在工作中遇到一个场景,发现flatMap简直太方便了,这里总结一下flatMap的常规使用。附带讲一下,使用Java8实现集合的并、交、差操作,其实之前也讲过一种使用Guava的实现方式,具体请参考Guava集合工具

  • flatMap

首先看一下一种场景,存在一个Map<Integer, ListContainer>,ListContainer中存在一个List<AClass>成员变量。有这样一个需求,讲Map中values中所有的List<AClass>组合成一个List<AClass>。我们也许会这样操作:

List<AClass> resultAClassList = Lists.newArrayList();
for (ListContainer tmp : map.values()){
    resultAClassList.addAll(tmp.getLst());
}

这还是只存在一层List的情况,如果存在多层,for还需要嵌套,使用起来很不方便。后来查到,Java8 Stream的flatMap操作可以很好地适用这种场景,首先看一下flatMap方法定义:

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

参数是一个Function函数式接口,提供T到Stram的转换。其实参考方法实现,flatMap就是将Function转化后的Stram合并成一个Stream。下面看一下使用示例,完成上述相同的功能:

@Test
public void mergeMapValuesTest(){
    Map<Integer, ListContainer> map = Maps.newHashMap();
    List<AClass> aClassList1 = Lists.newArrayList();
    AClass aClass = new AClass(1, "zhuoli1", "haha1");
    aClassList1.add(aClass);
    aClassList1.add(new AClass(2, "zhuoli2", "haha2"));
    aClassList1.add(new AClass(3, "zhuoli3", "haha3"));

    List<AClass> aClassList2 = Lists.newArrayList();
    aClassList2.add(aClass);
    aClassList2.add(new AClass(5, "zhuoli5", "haha5"));
    aClassList2.add(new AClass(6, "zhuoli6", "haha6"));

    /*交集*/
    /*[AClass(id=1, name=zhuoli1, description=haha1)]*/
    List<AClass> intersectResult = aClassList1.stream().filter(aClassList2::contains).collect(Collectors.toList());
    System.out.println(intersectResult);

    /*并集*/
    List<AClass> unionResult = Stream.of(aClassList1, aClassList2).flatMap(Collection::stream).distinct().collect(Collectors.toList());
    assertEquals(unionResult.size(), 5);
    System.out.println(unionResult);

    /*差集*/
    /*[AClass(id=2, name=zhuoli2, description=haha2), AClass(id=3, name=zhuoli3, description=haha3)]*/
    List<AClass> differenceResult = aClassList1.stream().filter(x -> !aClassList2.contains(x)).collect(Collectors.toList());
    System.out.println(differenceResult);

    map.put(1, new ListContainer(aClassList1));
    map.put(2, new ListContainer(aClassList2));

    /*合并多个list*/
    List<AClass> aClassListResult = map.values().stream().flatMap(listContainer -> listContainer.getLst().stream()).collect(Collectors.toList());
    /*注意跟并集的区别*/
    assertEquals(aClassListResult.size(), 6);
    System.out.println(aClassListResult);
}

分享一个flatMap的复杂操作,实现List<Data1>和List<Data2>根据Id进行连接,将连接结果输出为一个List<OutputData>:

@Data
@AllArgsConstructor
public class Data1 {
    private int id;
    private String name;
    private int amount;
}

@Data
@AllArgsConstructor
public class Data2 {
    private int id;
    private String name;
    private String type;
}

@Data
@AllArgsConstructor
public class OutputData {
    private int id;
    private String name;
    private String type;
    private int amount;
}


@Test
public void intersectByKeyTest(){
    List<Data2> listOfData2 = new ArrayList<Data2>();

    listOfData2.add(new Data2(10501, "JOE"  , "Type1"));
    listOfData2.add(new Data2(10603, "SAL"  , "Type5"));
    listOfData2.add(new Data2(40514, "PETER", "Type4"));
    listOfData2.add(new Data2(59562, "JIM"  , "Type2"));
    listOfData2.add(new Data2(29415, "BOB"  , "Type1"));
    listOfData2.add(new Data2(61812, "JOE"  , "Type9"));
    listOfData2.add(new Data2(98432, "JOE"  , "Type7"));
    listOfData2.add(new Data2(62556, "JEFF" , "Type1"));
    listOfData2.add(new Data2(10599, "TOM"  , "Type4"));


    List<Data1> listOfData1 = new ArrayList<Data1>();

    listOfData1.add(new Data1(10501, "JOE"    ,3000000));
    listOfData1.add(new Data1(10603, "SAL"    ,6225000));
    listOfData1.add(new Data1(40514, "PETER"  ,2005000));
    listOfData1.add(new Data1(59562, "JIM"    ,3000000));
    listOfData1.add(new Data1(29415, "BOB"    ,3000000));

    List<OutputData> result = listOfData1.stream()
            .flatMap(x -> listOfData2.stream()
                    .filter(y -> x.getId() == y.getId())
                    .map(y -> new OutputData(y.getId(), x.getName(), y.getType(), x.getAmount())))
            .collect(Collectors.toList());
    System.out.println(result);

    /*difference by key*/
    List<Data1> data1IntersectResult = listOfData1.stream().filter(data1 -> listOfData2.stream().map(Data2::getId).collect(Collectors.toList()).contains(data1.getId())).collect(Collectors.toList());
    System.out.println(data1IntersectResult);
}
  • faltMapToInt

首先看一下flatMapToInt方法定义:

IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);

跟flatMap不同的是,参数Function函数式接口提供由T到IntStream的转化,方法返回值是IntStream。

@Test
public void flatMapToIntTest() {
    List<List<String>> listOfLists = Arrays.asList(
            Arrays.asList("1", "2"),
            Arrays.asList("5", "6"),
            Arrays.asList("3", "4")
    );

    IntStream intStream =
            listOfLists.stream()
                    .flatMapToInt(childList ->
                            childList.stream()
                                    .mapToInt(Integer::new));

    int sum = intStream.peek(System.out::println).sum();
    System.out.println("sum: " + sum);
}

Stream接口中还存在类似的方法flatMapToDouble、flatMapToLong,使用方法跟flatMapToInt是一样的,这里就不多介绍了,仅罗列一下方法定义:

DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);
LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);

示例代码:码云 – 卓立 – Java8 flatMap示例

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/135925.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • sap安装配置_sapgui730安装指南

    sap安装配置_sapgui730安装指南一.下载和安装    WEBIDE是免安装的,下载完解压就行。       下载地址  Developerguid在线文档  在线文档打开会比较慢,可以下载下来观看。二.配置ABAP链接 在IDE的解压文件的配置文件夹中新建文件ER1(没有后缀名)  编辑新建文件添加如下内容:  Description=

    2022年10月18日
  • 阿里云windows server 安装软件_阿里云windows

    阿里云windows server 安装软件_阿里云windows在阿里云服务器上安装svn与在本地安装是一样的,详细步骤参考楼主之前的帖子http://blog.csdn.net/m0_37027631/article/details/60773156楼主一开始安装完后,访问服务端svn连接失败。原因是因为阿里云服务器中的80、443端口没有开放的原因。如何开放阿里云服务器中的端口请参考http://blog.csdn.net/m0_3702763

    2022年10月10日
  • python缩进块_Python缩进规则(包含快捷键)「建议收藏」

    和其它程序设计语言(如Java、C语言)采用大括号“{}”分隔代码块不同,Python采用代码缩进和冒号(:)来区分代码块之间的层次。在Python中,对于类定义、函数定义、流程控制语句、异常处理语句等,行尾的冒号和下一行的缩进,表示下一个代码块的开始,而缩进的结束则表示此代码块的结束。大理石平台精度等级注意,Python中实现对代码的缩进,可以使用空格或者Tab键实现。但无论…

  • chrome frame节点 取_Chrome Frame插件解决IE浏览器兼容问题

    chrome frame节点 取_Chrome Frame插件解决IE浏览器兼容问题时不时碰到客户的浏览器为IE7,IE8,甚至IE6的,他们不能升级浏览器,因为升级后,机器中其它的重要系统无法访问。而新系统的前端又需要浏览器的支持,比如H5,SVG等等,换框架结构,成本无疑是巨大的,而且风险不可控。针对此种情况,安装GoogleFrame是相对非常完美的解决方案,不要求升级浏览器,只安装一个插件,且对原系统无任何干扰,新系统也可根据情况对是否使用GoogleFrame插件进…

  • Iocomp控件教程之Analog Display—模拟显示控件(优于EDIT控件)[通俗易懂]

    Iocomp控件教程之Analog Display—模拟显示控件(优于EDIT控件)[通俗易懂]AnalogDisplay是简洁的显示控件,用于显示指定精确度和单位的模拟值(实数),可以将精确度设置为0,使显示结果为整数。第一步:建立MFC对话框第二步:插入AnalogDisplay控件第三步:单击控件-鼠标右键-添加成员变量完成添加变量的同时,控件的.h、.c文件也会被添加到程序中主要成员函数介绍://背景颜色I_analo

  • sql根据字段去重_sql如何去重查询

    sql根据字段去重_sql如何去重查询关于sql去重,我简单谈一下自己的简介,如果各位有建议或有不明白的欢迎多多指出。关于sql去重最常见的有两种方式:DISTINCT和ROW_NUMBER(),当然了ROW_NUMBER()除了去重还有很多其他比较重要的功能,一会我给大家简单说说我自己在实际中用到的。假如有张UserInfo表,如下图:现在我们要去掉完全重复的数据:SELECTDISTINCT*FROMdbo.UserInf…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号