美文网首页
LinkedHashMap源码分析

LinkedHashMap源码分析

作者: 言西枣 | 来源:发表于2016-05-21 20:35 被阅读140次

    源码来自jdk1.8

    • 继承了HashMap,是Map接口的Hash table和linked list实现,所以在迭代的时候的顺序是已知的,这个顺序可以是插入的顺序,也可以设为最后访问,也就是说可以实现一个LRU cache
    public class LinkedHashMap<K,V>
        extends HashMap<K,V>
        implements Map<K,V>
    {
         /**
         * The head (eldest) of the doubly linked list.
         */
        transient LinkedHashMap.Entry<K,V> head;
    
        /**
         * The tail (youngest) of the doubly linked list.
         */
        transient LinkedHashMap.Entry<K,V> tail;
    
        /**
         * The iteration ordering method for this linked hash map: <tt>true</tt>
         * for access-order, <tt>false</tt> for insertion-order.
         *
         * @serial
         */
        final boolean accessOrder;
        // ......
    }
    

    LinkedHashMap里的两个关键点,一是链表,二是accessOrder

    链表

    由于要维持一个双链表,所以LinkedHashMap里的节点继承了HashMap中的节点,添加了before,after两个成员变量

    static class Entry<K,V> extends HashMap.Node<K,V> {
            Entry<K,V> before, after;
            Entry(int hash, K key, V value, Node<K,V> next) {
                super(hash, key, value, next);
            }
        }
    

    LinkedHashMap重写了HashMap中的一些函数,如newNode、replacementNode、newTreeNode等,在重写的函数中添加了维持链表结构的函数,这样在添加节点等操作中能始终维持链表结构

    accessOrder

    如果在这是一个根据accessOrder来迭代的LinkedHashMap,那么在get和getOrDefault访问操作中还要增加更新链表结构的函数,将最近访问的节点放到链表最后

    void afterNodeAccess(Node<K,V> e) { // move node to last
            LinkedHashMap.Entry<K,V> last;
            if (accessOrder && (last = tail) != e) {
                LinkedHashMap.Entry<K,V> p =
                    (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
                p.after = null;
                if (b == null)
                    head = a;
                else
                    b.after = a;
                if (a != null)
                    a.before = b;
                else
                    last = b;
                if (last == null)
                    head = p;
                else {
                    p.before = last;
                    last.after = p;
                }
                tail = p;
                ++modCount;
            }
        }
    

    但无论是插入顺序还是访问顺序,LinkedHashMap里的iterator都是通过链表实现的,类似于LinkedList。

        abstract class LinkedHashIterator {
            LinkedHashMap.Entry<K,V> next;
            LinkedHashMap.Entry<K,V> current;
            int expectedModCount;
    
            LinkedHashIterator() {
                next = head;
                expectedModCount = modCount;
                current = null;
            }
    
            public final boolean hasNext() {
                return next != null;
            }
    
            final LinkedHashMap.Entry<K,V> nextNode() {
                LinkedHashMap.Entry<K,V> e = next;
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                if (e == null)
                    throw new NoSuchElementException();
                current = e;
                next = e.after;
                return e;
            }
    
            public final void remove() {
                Node<K,V> p = current;
                if (p == null)
                    throw new IllegalStateException();
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                current = null;
                K key = p.key;
                removeNode(hash(key), key, null, false, false);
                expectedModCount = modCount;
            }
        }
    
        final class LinkedKeyIterator extends LinkedHashIterator
            implements Iterator<K> {
            public final K next() { return nextNode().getKey(); }
        }
    
        final class LinkedValueIterator extends LinkedHashIterator
            implements Iterator<V> {
            public final V next() { return nextNode().value; }
        }
    
        final class LinkedEntryIterator extends LinkedHashIterator
            implements Iterator<Map.Entry<K,V>> {
            public final Map.Entry<K,V> next() { return nextNode(); }
        }
    
    

    相关文章

      网友评论

          本文标题:LinkedHashMap源码分析

          本文链接:https://www.haomeiwen.com/subject/lkrorttx.html