Java Map —— LinkedHashMap

4.LinkedHashMap = HashMap + 双向链表

  • before after构成双向链表
    static class Entry extends HashMap.Node {
        Entry before, after;
        Entry(int hash, K key, V value, Node next) {
            super(hash, key, value, next);
        }
    }
  • 关于put(key, value)
    step1.调用HashMap.put
    step2.调用HashMap.putVal
    step3.putVal中调用LinkedHashMap.newNode(hash, key, value, null);
    调用linkNodeLast将该结点加入到双向链表的末尾。
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node[] tab; Node p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
    Node newNode(int hash, K key, V value, Node e) {
        LinkedHashMap.Entry p =
            new LinkedHashMap.Entry(hash, key, value, e);
        linkNodeLast(p);
        return p;
    }

    private void linkNodeLast(LinkedHashMap.Entry p) {
        LinkedHashMap.Entry last = tail;
        tail = p;
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
    }
  • 关于get(key)
    accessOrder——true表示access-order,false表示insertion-order
    accessOrder为true就会将最近访问的结点放到链表末尾。
    public V get(Object key) {
        Node e;
        if ((e = getNode(hash(key), key)) == null)
            return null;
        if (accessOrder)
            afterNodeAccess(e);
        return e.value;
    }
  • 实现LRU
    这里的LRU将最老的放在链表头,最近刚访问过的放在链表尾,如果需要删除,就删除链表头。
    只需要重写其removeEldestEntry()
    HashMap.putVal方法中最后调用afterNodeInsertion
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        ...
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

LinkedHashMap实现了afterNodeInsertion,该方法调用了removeEldestEntry,若removeEldestEntry条件满足,就会删除head。

    void afterNodeInsertion(boolean evict) { // possibly remove eldest
        LinkedHashMap.Entry first;
        if (evict && (first = head) != null && removeEldestEntry(first)) {
            K key = first.key;
            removeNode(hash(key), key, null, false, true);
        }
    }

你可能感兴趣的:(Java Map —— LinkedHashMap)