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

时间:2019-05-15 18:23:07

标签: java java-stream

我对Java中的流有一个要求。 我需要遍历对象列表,其中每个对象都具有Integer属性和List属性。

我需要的是,如果相同的对象具有相同的ID,则需要合并列表。 让我用一些简单的代码来说明示例:

这里只定义了两个简单的类:

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方法中,为示例的用法创建相同的对象:

    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的包装对象,其list属性中包含2个元素,即元素内容A和元素内容B

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

如何使用Streams获得此结果?我想不到任何优雅的解决方案!

谢谢!

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

3 个答案:

答案 0 :(得分:2)

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

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()

答案 1 :(得分:1)

您可以使用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]]

答案 2 :(得分:0)

您可以尝试以下方法:

TO_DATE(TRIM(:DR430_LAST_MOD_DATE), 'YYYYMMDD')