关于java:ArrayListMultimap与LinkedListMultimap有什么不同?

How is ArrayListMultimap different from LinkedListMultimap?

所以,我只是在读取ArrayListMultimapLinkedListMultimap的javadoc,以便了解如何使用它们,我开始知道它们都支持重复的键值对(并且我的意思是相同的键,不同的值 - 如果 我理解正确。如果我错了,请纠正我)。 但是,我不明白它们之间的区别。 两者都用于存储重复的键值对。 它们不同的唯一部分是它们的实现,即ArrayListMultimap是作为数组实现的,LinkedListMultimap是作为LinkedList实现的? 另外,它们在性能上有何不同? 我知道我问了很多,但我真的不知道在哪里可以找到答案。


它在文档......和代码中。基本上除了你已经看到的一个区别(List实现选择)之外,它们还使用不同的Map实现。所以:

  • ArrayListMultimap使用HashMap表示map和ArrayList cor集合,这意味着未定义entries()asMap().keySet()asMap.entrySet()等方法的迭代顺序。这是ListMultimap的简单实现,你应该从这个开始。
  • LinkedListMultimap使用LinkedList进行收集和专用数据结构(自定义链表)以维护上述方法的迭代顺序:

    Order is maintained using a linked list containing all key-value
    pairs. In addition, a series of disjoint linked lists of
    "siblings", each containing the values for a specific key, is used
    to implement ValueForKeyIterator in constant time.

    此外,它使用很少的其他结构来维护"链表"式行为:

    1
    2
    3
    4
    5
    private transient Node<K, V> head; // the head for all keys
    private transient Node<K, V> tail; // the tail for all keys
    private transient Multiset<K> keyCount; // the number of values for each key
    private transient Map<K, Node<K, V>> keyToKeyHead; // the head for a given key
    private transient Map<K, Node<K, V>> keyToKeyTail; // the tail for a given key

此外,内存占用是这些Multimap实现中使用的后备集合的含义 - 请参阅此比较(可能不是100%最新)。

就个人而言,当我需要具有定义的密钥迭代顺序的高效,可变ListMultimap时,我使用"自定义"ListMultimap(使用MultimapBuilder创建,自v16.0起在Guava中创建):

1
2
ListMultimap<String, Integer> treeListMultimap =
    MultimapBuilder.linkedHashKeys().arrayListValues().build();

在v16.0之前创建自定义Multimap s更详细(使用Multimaps.newListMultimap):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * Creates {@link ListMultimap} preserving insertion order of keys and values
 * (it's backed by {@link LinkedHashMap} and {@link ArrayList}).
 */

public static <K, V> ListMultimap<K, V> newLinkedArrayListMultimap() {
  return Multimaps.newListMultimap(
      Maps.<K, Collection<V>>newLinkedHashMap(),
      new Supplier<List<V>>() {
          @Override
          public List<V> get() {
            return Lists.newArrayList();
          }
      });
}