LinkedHashMap源码分析

1. LinkedHashMap.Entry

LinkedHashMap继承自HashMap,在其内部维护了一个双向链表

static class Entry<K,V> extends HashMap.Node<K,V> { // HashMap.TreeNode继承自此类
    Entry<K,V> before, after; // 前置节点和后置节点
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}

2. LinkedHashMap

1' get + afterNodeAccess + accessOrder(true):将被访问的节点移至双向链表尾部

2' newNode、newTreeNode:将新插入节点添加到双向链表尾部

3' afterNodeInsertion + removeEldestEntry:新插入节点后,删双向链表头节点(最旧节点)

4' afterNodeRemoval:维护节点前后指针、双向链表头尾节点

5' replacementNode:红黑树转链表时,维护节点前后指针、双向链表头尾节点

6' replacementTreeNode:链表转红黑树时,维护节点前后指针、双向链表头尾节点

public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
    ...transient LinkedHashMap.Entry<K,V> head; // 双向链表头节点
    transient LinkedHashMap.Entry<K,V> tail; // 双向链表尾节点
    // accessOrder置为true && 继承LinkedHashMap,覆盖removeEldestEntry方法:可实现LRU(Least Recently Used)算法
    final boolean accessOrder;
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) { return false; } ... public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; } // 覆盖(accessOrder + afterNodeAccess) public V get(Object key) { Node<K,V> e; if ((e = getNode(hash(key), key)) == null) // HashMap.getNode return null; if (accessOrder) afterNodeAccess(e); // 在访问e后,将e移至双向链表尾部 return e.value; } // 覆盖(HashMap中为noop),见HashMap.putVal方法 void afterNodeAccess(Node<K,V> e) { LinkedHashMap.Entry<K,V> last; if (accessOrder && (last = tail) != e) { // accessOrder && e不是双向链表尾节点 LinkedHashMap.Entry<K,V> p = (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after; p.after = null; if (b == null) // p为头结点 head = a; else b.after = a; if (a != null) // p非尾节点 a.before = b; else last = b; if (last == null) // a == b == null head = p; else { p.before = last; last.after = p; } tail = p; ++modCount; } } // 覆盖(HashMap中为noop),见HashMap.putVal方法 void afterNodeInsertion(boolean evict) { // 删除双向链表头节点 LinkedHashMap.Entry<K,V> first; // evit(为true,见HashMap.put方法)&& 双向链表不为空 && removeEldestEntry条件成立 if (evict && (first = head) != null && removeEldestEntry(first)) { K key = first.key; removeNode(hash(key), key, null, false, true); } } // 覆盖(HashMap.Node -> LinkedHashMap.Entry + 将节点添加到双向链表尾部),见HashMap.putVal方法 Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) { LinkedHashMap.Entry<K,V> p = new LinkedHashMap.Entry<K,V>(hash, key, value, e); linkNodeLast(p); // 将p链接至双向链表尾部 return p; } // 覆盖(+ 链接p至双向链表尾部),见HashMap.TreeNode.putTreeVal方法 TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) { TreeNode<K,V> p = new TreeNode<K,V>(hash, key, value, next); linkNodeLast(p); // 将p链接至双向链表尾部 return p; } private void linkNodeLast(LinkedHashMap.Entry<K,V> p) { LinkedHashMap.Entry<K,V> last = tail; tail = p; if (last == null) // 双向链表为空 head = p; else { // 双向链表不为空 p.before = last; last.after = p; } } // 覆盖(HashMap中为noop),见HashMap.removeNode方法 void afterNodeRemoval(Node<K,V> e) { LinkedHashMap.Entry<K,V> p = (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after; p.before = p.after = null; if (b == null) // p为头结点 head = a; else b.after = a; if (a == null) // p为尾节点 tail = b; else a.before = b; } // 覆盖(HashMap.Node -> LinkedHashMap.Entry、+ 转移before和after属性),见HashMap.TreeNode.untreeify方法 Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) { LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p; LinkedHashMap.Entry<K,V> t = new LinkedHashMap.Entry<K,V>(q.hash, q.key, q.value, next); transferLinks(q, t); // before和after属性转移(可能修改双向链表的头尾节点) return t; } // 覆盖(+ 转移before和after属性),见HashMap.treeifyBin方法 TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) { LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p; TreeNode<K,V> t = new TreeNode<K,V>(q.hash, q.key, q.value, next); transferLinks(q, t); // before和after属性转移(可能修改双向链表的头尾节点) return t; } private void transferLinks(LinkedHashMap.Entry<K,V> src, LinkedHashMap.Entry<K,V> dst) { LinkedHashMap.Entry<K,V> b = dst.before = src.before; LinkedHashMap.Entry<K,V> a = dst.after = src.after; if (b == null) // src为头节点 head = dst; else b.after = dst; if (a == null)// src为尾节点 tail = dst; else a.before = dst; } ... }

3. 迭代器

用LinkedHashMap.Entry.after对双向链表节点进行迭代

// LinkedEntrySet迭代器
final class LinkedEntryIterator extends LinkedHashIterator implements Iterator<Map.Entry<K,V>> {
    public final Map.Entry<K,V> next() { return nextNode(); }
}

// LinkedKeySet迭代器
final class LinkedKeyIterator extends LinkedHashIterator implements Iterator<K> {
    public final K next() { return nextNode().getKey(); }
}

// LinkedValues迭代器
final class LinkedValueIterator extends LinkedHashIterator implements Iterator<V> {
    public final V next() { return nextNode().value; }
}
// 用LinkedHashMap.Entry的after属性进行迭代
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); // HashMap.removeNode
        expectedModCount = modCount; // HashMap.removeNode将使modCount++
    }
}
posted @ 2017-12-25 14:01  Uncle_Bjorney  阅读(162)  评论(0编辑  收藏  举报