首页 > 解决方案 > Java Streams。如何将多个对象的列表加入和组合成一个对象?

问题描述

我有一个与 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 个 Wrappers 添加到列表中,但其中 2 个具有相同的 ID

我想要的是当数组中的包装器 ID 相同时,只需合并两个列表。所以在这个例子中,结果应该是:

包含 2 个元素的列表

元素 1 :ID 为 1 的包装对象,在其列表属性中包含 2 个元素,元素内容 A 和元素内容 B

元素 2:ID 为 2 的包装对象,其列表属性中有 4 个元素,元素内容 C,元素内容 D,元素内容 E 和元素内容 F。

如何使用 Streams 实现此结果?我想不出任何优雅的解决方案!

提前致谢!

List<Wrapper> combinedList=list.stream().....

标签: javajava-stream

解决方案


您可以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().


推荐阅读