总览
开局一张图
LinkedHashMap源码整体结构
- public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
LinkedHashMap继承了HashMap,那不同点在哪里呢?
新增变量
- final boolean accessOrder;
- transient LinkedHashMap.Entry<K,V> tail;
- transient LinkedHashMap.Entry<K,V> head; 从名字上可以看出head,tail是双向链表的头尾节点,那accessOrder的作用呢?
/**
* The iteration ordering method for this linked hash map: <tt>true</tt>
* for access-order, <tt>false</tt> for insertion-order.
* 翻译过来就是这个值影响迭代顺序,true迭代顺序是访问顺序,false迭代顺序是插入顺序
* @serial
*/
final boolean accessOrder;
新增内部类
- static class Entry<K,V> extends HashMap.Node<K,V>
- final class LinkedKeySet extends AbstractSet
- final class LinkedValues extends AbstractCollection
- final class LinkedEntrySet extends AbstractSet<Map.Entry<K,V>>
- abstract class LinkedHashIterator
- final class LinkedKeyIterator extends LinkedHashIterator implements Iterator
- final class LinkedValueIterator extends LinkedHashIterator implements Iterator
- final class LinkedEntryIterator extends LinkedHashIterator implements Iterator<Map.Entry<K,V>>
细节
accessOrder变量影响
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;
}
/**
* {@inheritDoc}
*/
public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return defaultValue;
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;
}
}
链表的构建
可以发现LinkHashMap 并没有重写put方法,那双链表是怎么构建的呢?
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;
}
TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
TreeNode<K,V> p = new TreeNode<K,V>(hash, key, value, next);
//关键代码
linkNodeLast(p);
return p;
}
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}
还记得HashMap的着3个方法么?
// Callbacks to allow LinkedHashMap post-actions
void afterNodeAccess(Node<K,V> p) { }
void afterNodeInsertion(boolean evict) { }
void afterNodeRemoval(Node<K,V> p) { }
//afterNodeAccess 前面已经贴出来了
void afterNodeInsertion(boolean evict) { // possibly remove eldest
LinkedHashMap.Entry<K,V> first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
removeNode(hash(key), key, null, false, true);
}
}
void afterNodeRemoval(Node<K,V> e) { // unlink
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)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;
}