【问题标题】:Deletion in LinkedHashMap vs HashMapLinkedHashMap 与 HashMap 中的删除
【发布时间】:2015-06-05 08:12:28
【问题描述】:

LinkedHashMap 中的删除需要线性时间是否正确。由于我们需要从维护插入顺序的链表中删除键,这将花费O(n) 时间。在常规的HashMap 中删除需要固定的时间。

【问题讨论】:

  • 对特定链表节点的引用与条目一起存储在内部,因此删除也是 O(1)
  • @SashaSalauyou 是的,这是有道理的。如果你发布你的答案,我会接受它,因为你明确说明了为什么它是不变的。
  • 谢谢,但我相信这不是答案,只是评论=)

标签: java collections hashmap time-complexity


【解决方案1】:

根据Javadocs,不是:

此类提供所有可选的Map 操作,并允许空元素。与HashMap 一样,它为基本操作(addcontainsremove)提供恒定时间性能,假设哈希函数将元素正确地分散在桶中。由于维护链表的额外费用,性能可能略低于 HashMap,但有一个例外:迭代 LinkedHashMap 的集合视图需要与 size成正比的时间> 的地图,无论其容量如何。对HashMap 的迭代可能会更昂贵,所需时间与其容量成正比。

LinkedHashMap 不会覆盖HashMap#remove(Object key) 方法。后者从表中移除该键对应的条目,并在被删除条目上调用recordRemoval()方法,该方法调整被移除条目的上一个和下一个的链接。为了删除某个索引处的节点,列表没有迭代。

【讨论】:

    【解决方案2】:

    LinkedHasMap 使用的是 HashMap.Entry 子类的 Entry,因此成本较高但仍保持不变。

    每次在 HashMap 中删除条目时,都会调用方法 recordRemoval(HashMap m)。它在 HashMap.Entry 中的实现是空的,但是 LinkedHasMap。条目只是从列表中删除条目):

    /**
     * Removes this entry from the linked list.
     */
    private void remove() {
        before.after = after;
        after.before = before;
    

    }

    顺序如下:

    • 在 HashMap 中移除实现调用 removeEntryForKey (HashMap:line551)

      public V remove(Object key) {
          Entry<K,V> e = removeEntryForKey(key);
          return (e == null ? null : e.value);
      }
      
    • HashMap 中的removeEntryForKey 调用entry.recordRemoval(this) (HashMap:line560)

      final Entry<K,V> removeEntryForKey(Object key) {
          [...]
          while (e != null) {
              Entry<K,V> next = e.next;
              Object k;
              if (e.hash == hash &&
                  ((k = e.key) == key || (key != null && key.equals(k)))) {
                  [...]
                  e.recordRemoval(this);
                  return e;
              }
              prev = e;
              e = next;
          }
          return e;
      }
      
    • LinkedHasMap.Entry中的recordRemoval实现调用上面的remove方法,为O(1) (LinkedHashMap:line357)

      void recordRemoval(HashMap<K,V> m) {
          remove();
      }
      

    HashMap 的来源: http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/share/classes/java/util/HashMap.java

    LinkedHashMap 的来源: http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/share/classes/java/util/LinkedHashMap.java

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-11
      • 2011-03-02
      • 2011-02-22
      • 2021-03-24
      • 2017-05-26
      • 2012-05-13
      • 1970-01-01
      • 2011-01-25
      相关资源
      最近更新 更多