Map之LinkedHashMap

LinkedHashMap继承自HashMap. 通过Entry组成链表。 LinkedHashMap有个属性 accessOrder,它为true时,会把最近使用的entry放在前面,可以作为LRU缓存容器。默认accessOrder为false。LinkedHashMap会把插入的元素按先后顺序链接起来,如下图所示。

LinkedHashMap定义了head 和 tail两个entry, head是链表头,tail是链表尾。 通过tail节点找到链表上次添加的节点。

构造函数:

1. 

public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}

2.

public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}

3

public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}

4

public LinkedHashMap(Map<? extends K, ? extends V> m) {
super();
accessOrder = false;
putMapEntries(m, false);
}

5 此构造方法可以设置accessOrder的值为true.

public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}

 

6. LinkedHashMap重写了newNode()方法,新建entry后调用linkNodeLast(p)创建before和after链接。

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);
return p;
}

7.  removeEldestEntry((Map.Entry<K,V> eldest):boolean, 默认返回false,不会删除最老的节点。 可以覆盖这个方法,写自己的逻辑,返回true就会删除最老的节点。

 

8. LinkedHashMap重写了get()方法,实现了LRU。 访问的节点被放到双向链表的尾部。

public V get(Object key) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return null;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}

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;
}
}

9. forEach(BiConsumer<? super K, ? super V> action) , LinkedHashMap重写了该方法,用来遍历Entry链表。

posted @ 2020-12-23 18:22  闪闪的星光  阅读(167)  评论(0)    收藏  举报