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

Merge several Guava multisets into one

我想创建一个基于不可变 Guava 多重集的总和 (>2) 的不可变视图。多重集在列表中。我不想将内容复制到新的多重集中。我可能会使用 Multisets.sum(Multiset, Multiset) 并用它来减少我的多重集流,但是为每个中间步骤创建一个总和多重集似乎有点浪费。有没有更好的方法?

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

没有开箱即用的方法。

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

来源可用here

考虑到这一点,您可以创建自己的 class,其结构类似于 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);
  }
}

实际上 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) 可能只是在新的多重集中累积结果:

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

如果需要,拥有专用视图 class(请参阅@OliverGregoire 的回答)也是一种选择。