需先看HashMap源码:JDK8 HashMap源码笔记_hashmap(map<? extends k, ? extends v> m)-CSDN博客
一、LinkedHashMap的成员变量
//双向链表的头结点
transient LinkedHashMap.Entry<K,V> head;
//双向链表的尾结点
transient LinkedHashMap.Entry<K,V> tail;
//排序方式,true-访问顺序 false-插入顺序
//默认是插入顺序存储:accessOrder = false;
//accessOrder = true时表示访问顺序存储,就是最新访问的数据会放到链表尾部!(访问顺序的LinkedHashMap进行了get操作以后,重新排序,把get的Entry移动到双向链表的表尾。)
final boolean accessOrder;
LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>,可发现LinkedHashMap相比较HashMap多维护了2个成员变量head、tail,这2个变量就是LinkedHashMap用来实现双向链表的。
二、LinkedHashMap的静态内部类Entry
static class Entry<K,V> extends HashMap.Node<K,V> {
//新加成员变量before、after,用于双向链表的连接
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
也是比HashMap.Node多维护了2个成员变量before、after,用于双向链表的连接。
三、LinkedHashMap的newNode()方法
//HashMap.put()方法创建新Node会调用newNode()方法,LinkedHashMap重写了HashMap的newNode()
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;
}
//将新节点加入双向链表尾部
// link at the end of list
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;//旧尾节点作为新节点的before
last.after = p;//新节点作为旧尾节点的after
}
}
HashMap.put()方法创建新Node会调用newNode()方法,LinkedHashMap重写了HashMap的newNode()。所以,往LinkedHashMap中put()数据时会调用linkNodeLast(),将新节点加入双向链表。
jdk1.7是在构造函数中调用init()方法,init()中直接new Entry()创建了一个空节点对象作为双向链表的初始节点。jdk1.8去除了这一操作,没有去new一个空节点作为链表初始节点,这样,链表中维护的节点就都是LinkedHashMap中实际存在的对象了。
四、LinkedHashMap.forEach()数据迭代方法
public void forEach(BiConsumer<? super K, ? super V> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
//从双向链表的head开始,依次after迭代。所以取数据和存数据顺序能相同。
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
action.accept(e.key, e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
}
五、LinkedHashMap的数据结构图
实际上图是jdk1.7的LinkedHashMap的数据结构,jdk1.8中Entry header就是Entry1,偷懒拿来用一下。