LinkedHashMap的Entry继承自HashMap.Node增加了before, after,在HashMap的基础上维护了一个双向链表
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
并记录了头节点和尾节点
transient LinkedHashMap.Entry<K,V> head;
transient LinkedHashMap.Entry<K,V> tail;
head:新插入值和获取过的放在链表尾
tail:迭代器遍历时从链表头开始
构造函数指定accessOrder访问顺序,默认为false,LinkedHashMap默认记录插入顺序
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
LinkedHashMap的put方法为HashMap的put方法,put会调用afterNodeAccess(),afterNodeAccess在HashMap中是空实现,LinkedHashMap重写了这个方法
afterNodeAccess(e);
//HashMap
void afterNodeAccess(Node<K,V> p) { }
//LinkedHashMap
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;
}
}
accessOrder为true时记录访问顺序,get操作也会调用afterNodeAccess()
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;
}
记录访问顺序的LinkedHashMap可以用于实现LRU缓存
HashMap的put方法会调用afterNodeInsertion()在HashMap中为空实现,LinkedHashMap重写了afterNodeInsertion()调用removeEldestEntry(),如果为默认返回false。继承LinkedHashMap重写其removeEldestEntry即可。
public static class LRUCache extends LinkedHashMap
{
public LRUCache(int maxSize)
{
super(maxSize, 0.75F, true);
//缓存的最大容量
maxElements = maxSize;
}
protected boolean removeEldestEntry(java.util.Map.Entry eldest)
{
return size() > maxElements;
}
private static final long serialVersionUID = 1L;
protected int maxElements;
}