使用Java streams合并列表中相同对象下的列表

使用Java streams合并列表中相同对象下的列表,java,java-8,java-stream,collectors,Java,Java 8,Java Stream,Collectors,我有两个对象,如下所示: public class A { private Integer id; private String name; private List<B> list; public A(Integer id, String name, List<B> list) { this.id = id; this.name = name; this.list = list;

我有两个对象,如下所示:

public class A {
    private Integer id;
    private String name;
    private List<B> list;

    public A(Integer id, String name, List<B> list) {
        this.id = id;
        this.name = name;
        this.list = list;
    }

    //getters and setters
}
因此,A持有B的列表,A的列表如下所示:

    List<A> list = new ArrayList<>();
    list.add(new A(1, "a_one", Arrays.asList(new B(1, "b_one"), new B(2, "b_two"))));
    list.add(new A(2, "a_two", Arrays.asList(new B(2, "b_two"))));
    list.add(new A(1, "a_one", Arrays.asList(new B(3, "b_three"))));
    list.add(new A(2, "a_two", Arrays.asList(new B(4, "b_four"), new B(5, "b_five"))));
    list.add(new A(3, "a_three", Arrays.asList(new B(4, "b_four"), new B(5, "b_five"))));
Map<Integer, A> result = listOfA.stream()
    .collect(Collectors.toMap(A::getId, A::new, A::merge));

Collection<A> result = map.values();
我确实使用以下代码合并了列表:

List<A> resultList = new ArrayList<>();
list.forEach(a -> {
    if (resultList.stream().noneMatch(ai -> ai.getId().equals(a.getId()))) {
        a.setList(list.stream().filter(ai -> ai.getId().equals(a.getId()))
                .flatMap(ai -> ai.getList().stream()).collect(Collectors.toList()));
        resultList.add(a);
    }
});
List resultList=new ArrayList();
列表。forEach(a->{
if(resultList.stream().noneMatch(ai->ai.getId().equals(a.getId())){
a、 setList(list.stream().filter(ai->ai.getId().equals(a.getId()))
.flatMap(ai->ai.getList().stream()).collect(collector.toList());
结果列表。添加(a);
}
});
我的问题是,使用流收集器有没有合适的方法来实现这一点?

集合合并(列表){
Collection<A> merge(List<A> list) {
    return list.stream()
            .collect(Collectors.toMap(a -> a.id, Function.identity(), this::merge))
            .values();
}

A merge(A a1, A a2) {
    if (!a1.name.equals(a2.name)) {
        throw new IllegalArgumentException("We assumed same id means same name");
    }
    return new A(a1.id, a1.name, union(a1.list, a2.list));
}

List<B> union(List<B> l1, List<B> l2) {
    List<B> result = new ArrayList<>(l1);
    result.addAll(l2);
    return result;
}
return list.stream() .collect(Collectors.toMap(a->a.id,Function.identity(),this::merge)) .values(); } 合并(a1、a2){ 如果(!a1.name.equals(a2.name)){ 抛出新的IllegalArgumentException(“我们假设相同的id意味着相同的名称”); } 返回新的A(a1.id,a1.name,union(a1.list,a2.list)); } 列表联合(列表l1、列表l2){ 列表结果=新的ArrayList(l1); 结果:addAll(l2); 返回结果; }
如果您可以使用vanilla Java,这里是一个非常简单的解决方案。列表将立即迭代

Map<Integer, A> m = new HashMap<>();
for (A a : list) {
    if (m.containsKey(a.getId()))
        m.get(a.getId()).getList().addAll(a.getList());
    else
         m.put(a.getId(), new A(a.getId(), a.getName(), a.getList()));
}
List<A> output =  new ArrayList<>(m.values());
Map m=newhashmap();
对于(A:列表){
if(m.containsKey(a.getId()))
m、 get(a.getId()).getList().addAll(a.getList());
其他的
m、 put(a.getId(),新的a(a.getId(),a.getName(),a.getList());
}
列表输出=新的ArrayList(m.values());

假设类
A
有一个有效复制
列表
属性的复制构造函数和一个合并
A
的两个实例的方法:

public A(A another) {
    this.id = another.id;
    this.name = another.name;
    this.list = new ArrayList<>(another.list);
}

public A merge(A another) {
    list.addAll(another.list):
    return this;
}

如果您不想使用额外的函数,可以执行以下操作:可读且易于理解,首先按id分组,使用列表中的第一个元素创建一个新对象,然后加入所有B类以最终收集a

List方法。在这里,当fst为null时,您将使用Java8可选类创建新的


BinaryOperator方法。

可能有一个合适的way@Jose你为什么认为那是个不错的谢谢你。然而,香草爪哇对我来说太甜了。我需要收藏家的痛苦:)
public A(A another) {
    this.id = another.id;
    this.name = another.name;
    this.list = new ArrayList<>(another.list);
}

public A merge(A another) {
    list.addAll(another.list):
    return this;
}
Map<Integer, A> result = listOfA.stream()
    .collect(Collectors.toMap(A::getId, A::new, A::merge));

Collection<A> result = map.values();
List<A> result = new ArrayList<>(map.values());