我使用Multiset可以轻松访问元素的频率,但是我意识到有Collections#frequency(Collection<?>, Object)可以对任何集合进行相同的操作。那么使用Multiset有什么意义呢?性能是这里的问题吗?

最佳答案

Multiset#count()的番石榴文档
不得不说:


  请注意,对于基于Object.equals(java.lang.Object)的多重集,此结果与Collections.frequency(java.util.Collection,java.lang.Object)的结果相同(可能表现较差)。


因此,是的,我怀疑性能是这里的问题。

我认为Multiset#count效率更高,因为Collections#frequency遍历整个集合。对于要检查其频率的对象o,它将遍历集合中的所有元素e并检查(o == null ? e == null : o.equals(e))

对于Multiset(这是一个接口),count的确切实现取决于类。例如,如果它是HashMultiset,则它由HashMap支持。有关如何比遍历整个集合更有效的详细信息,请查看以下答案:How does a Java HashMap handle different objects with the same hash code?

Guava code如下

public int count(@Nullable Object element) {
    Count frequency = Maps.safeGet(backingMap, element);
    return (frequency == null) ? 0 : frequency.get();
}


同样,对于保持其元素顺序并由AVL树支持的TreeMultiset,可以用O(log(n))步而不是O(n)获得count,其中n是大小的集合。 Guava code如下:

public int count(@Nullable Object element) {
    try {
      @SuppressWarnings("unchecked")
          E e = (E) element;
          AvlNode<E> root = rootReference.get();
          if (!range.contains(e) || root == null) {
              return 0;
          }
      return root.count(comparator(), e);
    } catch (ClassCastException e) {
          return 0;
    } catch (NullPointerException e) {
          return 0;
    }
}

10-05 21:51