1 首先来看一下LinkedHashMap的继承关系
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
可以看出LinkedHashMap是继承了HashMap,它主要在链表的基础上增加了一个双向链表,重复的key值插入不会改变顺序,适用于使用者需要返回一个顺序相同的map对象的情况。允许放入key和value都为null的元素
2 成员变量
链表节点基本上是继承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;
/**
* 排序规则方式
* true 按访问顺序排序
* false 默认按插入顺序排序
*/
final boolean accessOrder;
3 构造方法
构造方法
1.
/**
* 调用HashMap的构造方法
*/
public LinkedHashMap() {
super();
//默认按插入顺序排序
accessOrder = false;
}
2.
/**
* 调用HashMap的构造方法
*/
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
//默认按插入顺序排序
accessOrder = false;
}
3.
/**
* 调用HashMap的构造方法
*/
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
//默认按插入顺序排序
accessOrder = false;
}
4.
/**
* 调用HashMap的构造方法
*/
public LinkedHashMap(Map<? extends K, ? extends V> m) {
super();
//默认按插入顺序排序
accessOrder = false;
putMapEntries(m, false);
}
5.
/**
* 调用HashMap的指定参数的构造方法
* 并且指定排序方式
*/
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
4 核心方法
LinkedHashMap的添加删除基本都与HashMap一样,只是在添加和删除之后还增加了调整的方法
在访问过后将链表移至尾部
void afterNodeAccess(Node<K,V> e) { // move node to last
LinkedHashMap.Entry<K,V> last;
//当accessOrder为true 并且e不是最后一个节点的时
if (accessOrder && (last = tail) != e) {
//a为p的下一个节点
//b为p的上一个节点
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
//p的下一个节点置null
p.after = null;
//b==null,即当前节点为首节点,更新首节点为a
if (b == null)
head = a;
else//当前节点不是首节点,修改b的下一个节点为a
b.after = a;
if (a != null) //a!=null,即当前结点不是尾节点
a.before = b;//更新a的上一个节点为b
else
last = b;//最后一个节点更新为b
if (last == null)//如果最后一个节点为null
head = p;//首节点更新为p
else {
p.before = last;//p的上一个节点更新为最后一个节点
last.after = p;//最后一个节点的下一个节点更新为p
}
//尾节点修改为p
tail = p;
//操作次数增加
++modCount;
}
}
删除一个节点时自动调整
void afterNodeRemoval(Node<K,V> e) { // unlink
//a为p的下一个节点
//b为p的上一个节点
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
p.before = p.after = null;
if (b == null) //b为null,即当前节点为首节点
head = a;//更新首节点为a
else//即当前节点不是首节点
b.after = a;//更新b的下一个节点为a
if (a == null)//a为null,当前节点为尾节点
tail = b;//更新尾节点为b
else//即当前节点不是尾节点
a.before = b;//更新a的上一个节点为b
}