LinkedHashMap与HashMap中的删除

时间:2015-03-31 20:28:23

标签: java collections hashmap time-complexity

LinkedHashMap中的删除是否需要线性时间。由于我们需要从保持插入顺序的链表中删除密钥,因此需要O(n)时间。常规HashMap删除需要一段时间。

2 个答案:

答案 0 :(得分:8)

根据Javadocs,它不是:

  

此类提供所有可选的Map操作,并允许null元素。与HashMap类似,它为基本操作(addcontainsremove)提供常量时间性能,假设散列函数分散元素适当的水桶之间。由于维护链表的额外费用,性能可能略低于HashMap的性能,但有一个例外:对LinkedHashMap的集合视图进行迭代需要与 size <成比例的时间/ em>的地图,无论其容量如何。 HashMap上的迭代可能更昂贵,需要时间与容量成比例。

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

答案 1 :(得分: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