LinkedHashMap是怎么保存节点的插入顺序或者访问顺序的呢?
默认accessOrder为false,保存的是插入顺序,插入时调用的还是父类HashMap的putVal()方法,在putVal()中创建新节点时是会调用newNode()方法来创建一个节点,在newNode()方法中会调用linkNodeLast()方法将节点添加到双向链表的尾部。
```java
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
//省略了部分代码...
tab[i] = newNode(hash, key, value, null);
//省略了部分代码...
}
//创建新节点
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;
}
//移动到双向链表尾部
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;
}
}
```
如果accessOrder为true,会保存访问顺序,在访问节点时,会调用afterNodeAccess()方法将节点先从双向链表移除,然后添加到链表尾部。
```java
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
{
//头结点,指向最老的元素
transient LinkedHashMap.Entry<K,V> head;
//尾节点,指向最新的元素
transient LinkedHashMap.Entry<K,V> tail;
//如果accssOrder为true,代表节点需要按照访问顺序排列,每次访问了元素,会将元素移动到尾部(代表最新的节点)。
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;
}
}
}
```
公众号进入网站体验更佳

