前面分析过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 .数据结构
好,今天先分析到这里,再见!