将几个Guava多重集合合并为一个

时间:2017-05-05 08:58:58

标签: java collections guava multiset

我想在数量(> 2)的不可变Guava多重集合的总和上创建一个不可变的视图。多重集合在列表中。我不想将内容复制到新的multiset中。我可以使用IPAddress1 IPaddress2 10.20.30.91 10.20.30.91 63.90.84.45 63.90.84.45 10.5.5.100 10.5.5.100 并使用它来减少我的Multisets流,但是为每个中间步骤创建一个求和的multiset似乎有点浪费。还有更好的方法吗?

换句话说:我想要一个类似于Multisets.sum(Multiset, Multiset)的方法,但是需要一个多重集的列表而不是两个。签名可以是:Multisets.sum(Multiset, Multiset)

2 个答案:

答案 0 :(得分:4)

没有开箱即用的方法。

但是,请记住,Guava是根据Apache许可证授权的,因此您可以查看并重用代码(只要您遵守许可证要求)。

来源可用here

考虑到这一点,您可以创建自己的类,结构与Guava的Multisets.sum(Multiset,Multiset)相似:

public class SummedMultiset<T> extends AbstractMultiset<T> {
  private final ImmutableList<Multiset<T>> multisets;
  public SummedMultiset(List<Multiset<T>> multisets) {
    this.multisets = ImmutableList.copyOf(multisets);
  }
  @Override public int count(Object element) {
    return multisets.stream().mapToInt(m -> m.count(element)).sum();
  }
  // Fill all the other methods seen in Guava's source.
}

当然,您可以在方法后隐藏该实现:

public class MoreMultisets {
  public static Multiset<T> sum(List<Multiset<T>> multisets) {
    return new SummedMultiset<>(multisets);
  }
}

答案 1 :(得分:2)

实际上Multisets.sum(Multiset, Multiset)是以不复制内容的方式实现的,而是在两个多个集合上创建一个视图,所以在你的情况下循环多个集合列表并且只将最终结果复制到一个新的不可变多重集就可以了(来自视图的开销对于少数多个集合而言无关紧要)。使用Java 8,您可以将Multiset的sumStream#reduce

结合使用
public <T> Multiset<T> sum(final List<Multiset<T>> multisets)
{
    return multisets.stream().reduce(ImmutableMultiset.of(), Multisets::sum);
}

修改

然而,虽然上面的方法不会涉及复制,但@LouisWasserman指出,最优解(YMMV)可能只是在新的multiset中累积结果:

public <T> ImmutableMultiset<T> sum(final List<Multiset<T>> multisets)
{
    final ImmutableMultiset.Builder<T> builder = ImmutableMultiset.builder();
    multisets.forEach(builder::addAll);
    return builder.build();
}

如果需要,还可以选择专门的视图课程(参见@ OliverGregoire的答案)。