如何通过更新重复项上的值来合并两个集合

时间:2018-04-27 15:31:20

标签: java collections java-8

我有这堂课:

class A{
 int count=0;


 //equals and hashCode implemented
}

创建两个集合:

Collection<A>  collection1;//something
Collection<A>  collection2;//something

连接集合:

Stream.concat(collection1.stream(), collection2.stream())
                //do something here???
                .distinct()
                .sorted(new Comparator<A>() {
                  @Override
                  public int compare(A o1, A o2) {

                     return new Integer(o1.count).compareTo(new Integer(o2.count));
                  }
                })
                .collect(Collectors.toList());

我想合并这两个列表,如果有任何重复,我想更新整数count;以上代码完全摆脱重复

例如, 假设我们在collection1和collection2中都有一个等于(o1.equals(o2) == true)的对象。一个人有count=10而另一个人有count=20我想拥有一个不同对象的集合,该对象包含count=30

有办法吗?

1 个答案:

答案 0 :(得分:3)

您无法使用当前的方法,而是可以使用toMap收集器:

Stream.concat(collection1.stream(), collection2.stream())
       .collect(Collectors.toMap(Function.identity(),Function.identity(),
       (left, right) -> {
          left.setCount(left.getCount() + right.getCount());
          return left;
       })).values()
         .stream()
         .sorted(Comparator.comparingInt(A::getCount))
         .collect(Collectors.toList());

这使用Stream.concatcollection1collection2合并为一个Stream<A>

然后我们调用toMap收集器,其中第一个Function.identity()选择源的元素作为键A,第二个Function.identity()也选择元素来源作为价值观;再次A,所以此时,您可以将数据可视化为Map<A, A>

函数(left, right) -> { ... }被称为合并函数,这是两个给定对象相等的地方,然后我们说取第一个元素的计数并取第二个元素的计数,将它们加在一起并将新值分配给我们要保留的其中一个元素,然后丢弃另一个元素。

因为您已覆盖equalshashcode,我们不需要明确地调用它,而是equals方法将被称为隐式以确定两个给定的对象是否相等。

一旦我们将元素收集到Map<A, A>,我们就会调用values()方法来检索Collection<A>,这样我们就可以使用它创建一个流stream()方法进一步使我们能够使用已排序的方法对流元素进行排序,最后使用toList收集器将其收集到List<A>