LinkedHashMap源码分析

前面分析过hashmap, 那么LinkedHashMap又是什么呢,LinkedHashMap继承于HashMap,并且实现map的接口,那我们再来分一下!

0. 属性

// 双向链表中最旧访问的节点
 transient LinkedHashMapEntry head;
// 双向链表中最近访问的节点
 transient LinkedHashMapEntry tail;
//accessOrder 如果为true的话,表示按照访问顺讯存储,false表示按照插入顺序存储
 final boolean accessOrder;

以上代码中,LinkedHashMapEntry这类是继承于HashMap.Node,并且扩充 before, after两个属性,这两个属性是干嘛的呢,简单的说是维护Entry插入的先后顺序。代码如下:

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

1. 方法

LinkedHashMap 很多方法都是继承hashmap,比如put,get等方法,比较有特点的是hashMap中的一下几个方法:

// Callbacks to allow LinkedHashMap post-actions
void afterNodeAccess(Node p) { }
void afterNodeInsertion(boolean evict) { }
void afterNodeRemoval(Node p) { }

这几个方法是让LinkedHashMap 来复写的。

afterNodeAccess

void afterNodeAccess(Node e) { // move node to last
        LinkedHashMapEntry last;
        if (accessOrder && (last = tail) != e) {
            LinkedHashMapEntry p =
                (LinkedHashMapEntry)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;
        }
    }

如果accessOrder为true的时候,将会把节点添加至链表尾部。

afterNodeInsertion

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

afterNodeInsertion方法用于移除链表中的最旧的节点对象,也就是链表头部的对象。但是在JDK1.8版本中,可以看到removeEldestEntry一直返回false,所以该方法并不生效。如果存在特定的需求,比如链表中长度固定,并保持最新的N的节点数据,可以通过重写该方法来进行实现。

afterNodeRemoval

 void afterNodeRemoval(Node e) { // unlink
        LinkedHashMapEntry p =
            (LinkedHashMapEntry)e, b = p.before, a = p.after;
        p.before = p.after = null;
        if (b == null)
            head = a;
        else
            b.after = a;
        if (a == null)
            tail = b;
        else
            a.before = b;
    }

如果移除了节点,那么在双链表中也要移除这个节点。

2 .数据结构

LinkedHashMap源码分析_第1张图片
结构示意图

好,今天先分析到这里,再见!

你可能感兴趣的:(LinkedHashMap源码分析)