Использование мультимножеств Guava или Collections.frequency ()?

Я использовал Multiset для имеют легкий доступ к частоте элементов, но я понимаю, что есть Collections#frequency(Collection<?>, Object), который делает то же самое для любой коллекции. Какой тогда смысл использовать Multiset? Является ли здесь проблемой производительность?


person seinecle    schedule 09.12.2014    source источник


Ответы (1)


Документация по Guava для 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. Для получения подробной информации о том, насколько это более эффективно, чем повторение всей коллекции, взгляните на этот ответ: Как Java HashMap обрабатывает разные объекты с одним и тем же хеш-кодом?.

код Guava выглядит следующим образом

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

Точно так же для TreeMultiset, который поддерживает порядок своих элементов и поддерживается деревом AVL, count можно получить за O(log(n)) шагов вместо O(n), где n — размер коллекции. код Guava заключается в следующем:

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;
    }
}
person Chthonic Project    schedule 09.12.2014
comment
Мне не хватает одного простого момента в вашем ответе: если Multiset содержит один элемент миллион раз, Collections.frequency будет повторять его миллион раз, в то время как Multiset просто находит элемент (применяется ваше обозначение Big-O) и говорит один миллион. - person maaartinus; 09.12.2014
comment
Для Multiset n обычно относится к количеству различных элементов, тогда как, например, для List это будет относиться к общему количеству элементов, различных или нет. - person Louis Wasserman; 09.12.2014