为了账号安全,请及时绑定邮箱和手机立即绑定

Java Streams。如何将多个对象的列表加入并合并为一个对象?

Java Streams。如何将多个对象的列表加入并合并为一个对象?

慕后森 2022-11-30 10:52:15
我有一个与 Java 中的 Streams 相关的要求。我需要遍历一个对象列表,其中每个对象都有一个 Integer 属性和一个 List 属性。我需要的是,如果相同的对象具有相同的 ID,我需要连接列表。让我用一些简单的代码来说明这个例子:这里只定义了 2 个简单的类:public static class Wrapper {  Integer id ;  List<Element> list;  public Wrapper(Integer id, List<Element> list) {    this.id = id;    this.list = list;  } }public static class Element {  String content ;   public Element(String content) {       this.content = content;   }  }现在在 Main Java 方法中,为示例的 porpuse 创建相同的对象:    List<Wrapper> list=new ArrayList();    ArrayList<Element> listForWrapper1= new ArrayList();    listForWrapper1.add(new Element("Content A"));    listForWrapper1.add(new Element("Content B"));    ArrayList<Element> listForWrapper2= new ArrayList();    listForWrapper2.add(new Element("Content C"));    listForWrapper2.add(new Element("Content D"));    ArrayList<Element> listForWrapper3= new ArrayList();    listForWrapper3.add(new Element("Content E"));    listForWrapper3.add(new Element("Content F"));     Wrapper wrapper1=new Wrapper(1,listForWrapper1);     Wrapper wrapper2=new Wrapper(2,listForWrapper2);     //Here this Wrapper has the same ID than wrapper2     Wrapper wrapper3=new Wrapper(2,listForWrapper3);     //Adding Elements to List     list.add(wrapper1);     list.add(wrapper2);     list.add(wrapper3);如您所见,我在列表中添加了 3 个包装器,但其中 2 个具有相同的 ID我想要的是当包装器 ID 在数组中相同时,只需合并两个列表。所以在这个例子中,结果应该是:包含 2 个元素的列表:元素 1 :ID 为 1 的包装对象,其列表属性中有 2 个元素,元素内容 A 和元素内容 B元素 2:ID 为 2 的包装对象,其列表属性中有 4 个元素,元素内容 C、元素内容 D、元素内容 E 和元素内容 F。如何使用 Streams 实现此结果?我想不出任何优雅的解决方案!提前致谢!List<Wrapper> combinedList=list.stream().....
查看完整描述

3 回答

?
守着一只汪

TA贡献1872条经验 获得超3个赞

您可以BinaryOperator<U> mergeFunction在 Collectors.toMap 中使用。


Collection<Wrapper> wrapperList = wrappers.stream()

        .collect(Collectors.toMap(Wrapper::getId, x -> x),

                (oldVal, newVal) -> {

                    oldVal.getElements().addAll(newVal.getElements());

                    return oldVal;

                }))

        .values();

在上面的代码中,我写mergeFunction了总是返回 oldVal(oldVal, newVal) -> oldVal但你可以改变你想要的方式。Lambda 函数x -> x也可以写成Function.identity().


查看完整回答
反对 回复 2022-11-30
?
HUWWW

TA贡献1874条经验 获得超12个赞

您可以使用Collectors.toMap()合并功能添加地图的值。


Map<Integer, Wrapper> collect = 

        list.stream()

            .collect(Collectors.toMap(w -> w.id,

                                      w -> w,

                                      (w1, w2) -> {

                                         w1.list.addAll(w2.list);

                                         return w1;

                                      })

            );

在职的


import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import java.util.stream.Collectors;


public class Main {

    public static void main(String[] args) {

        List<Wrapper> list=new ArrayList();

        ArrayList<Element> listForWrapper1= new ArrayList();

        listForWrapper1.add(new Element("Content A"));

        listForWrapper1.add(new Element("Content B"));


        ArrayList<Element> listForWrapper2= new ArrayList();

        listForWrapper2.add(new Element("Content C"));

        listForWrapper2.add(new Element("Content D"));


        ArrayList<Element> listForWrapper3= new ArrayList();

        listForWrapper3.add(new Element("Content E"));

        listForWrapper3.add(new Element("Content F"));


        Wrapper wrapper1=new Wrapper(1,listForWrapper1);

        Wrapper wrapper2=new Wrapper(2,listForWrapper2);

        //Here this Wrapper has the same ID than wrapper2

        Wrapper wrapper3=new Wrapper(2,listForWrapper3);



        //Adding Elements to List

        list.add(wrapper1);

        list.add(wrapper2);

        list.add(wrapper3);


Map<Integer, Wrapper> collect =

        list.stream()

            .collect(Collectors.toMap(w -> w.id,

                                      w -> w,

                                      (w1, w2) -> {

                                         w1.list.addAll(w2.list);

                                         return w1;

                                      })

            );

        System.out.println( collect.values() );

    }

}


 class Wrapper {

    Integer id ;

    List<Element> list;


    public Wrapper(Integer id, List<Element> list) {

        this.id = id;

        this.list = list;

    }


     @Override

     public String toString() {

         return id + ":" + list;

     }

 }


 class Element {

    String content ;


    public Element(String content) {

        this.content = content;

    }


     @Override

     public String toString() {

         return content;

     }

 }

输出


[1:[Content A, Content B], 2:[Content C, Content D, Content E, Content F]]


查看完整回答
反对 回复 2022-11-30
?
胡子哥哥

TA贡献1825条经验 获得超6个赞

你可以试试这个:


Map<Integer, Wrapper> map = list.stream().collect(Collectors.toMap(wrapper -> wrapper.id /*Use the ids as the keys*/, wrapper -> wrapper /*Return the same wrapper as the value*/, (w1, w2) -> {

         w1.list.addAll(w2.list); // If a wrapper with the same id is found, then merge the list of wrapper 2 to the list of wrapper 1 and return wrapper 1.

         return w1;

     }));


list = new ArrayList<>(map.values()); // Create new ArrayList with the values of the map.




System.out.println(list); // [cci.Test$Wrapper@4eec7777, cci.Test$Wrapper@3b07d329]


查看完整回答
反对 回复 2022-11-30
  • 3 回答
  • 0 关注
  • 520 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号