继承HashMap
Entry继承HashMap的Node
static class Entry extends HashMap.Node {
Entry before, after;
Entry(int hash, K key, V value, Node next) {
super(hash, key, value, next);
}
}
accessOrder:true访问顺序,false插入顺序,测试代码如下
public static void main(String[] args) {
LinkedHashMap map = new LinkedHashMap(0, 0.75f, true);// false
map.put("1", "value1");
map.put("2", "value2");
map.put("3", "value3");
print(map);
map.get("2");
//map.getOrDefault("2","default");
print(map);
}
accessOrder = true
1 value1
2 value2
3 value3
--------------------------------------
1 value1
3 value3
2 value2
--------------------------------------
accessOrder = false
1 value1
2 value2
3 value3
--------------------------------------
1 value1
2 value2
3 value3
--------------------------------------
如果为false,get之后Entry存储顺序还是put的顺序,如果为true择在get之后会把get的Entry放到队列尾部。
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
this.accessOrder = false;
}
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
this.accessOrder = false;
}
public LinkedHashMap() {
super();
this.accessOrder = false;
}
public LinkedHashMap(Map extends K, ? extends V> m) {
super();
this.accessOrder = false;
this.putMapEntries(m, false);
}
// 实现Lru效果要实现3个参数构造方法
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
LinkedHashMap的put直接调用了HashMap的put方法。
put方法把一个Entry put到Map中,在HashMap中调用newNode生成的是HashMap.Node,在LinkedHashMap中newNode生成的是LinkedHashMap.Entry,这里就是为啥LinkeHashMap的afterNodeAccess中Node
if ((p = tab[i = (n - 1) & hash]) == null) {
tab[i] = this.newNode(hash, key, value, null);
}else{
...
this.newNode(hash, key, value, null);
}
// HashMap中实现的该方法
Node newNode(int hash, K key, V value, Node next) {
return new Node<>(hash, key, value, next);
}
// LinkedHashMap中实现的该方法
Node newNode(int hash, K key, V value, Node e) {
LinkedHashMap.Entry p =
new LinkedHashMap.Entry(hash, key, value, e);
// 把生成的节点放到尾部 详见3.2
this.linkNodeLast(p);
return p;
}
把新生成的Node放到链表尾部
// link at the end of list
private void linkNodeLast(LinkedHashMap.Entry p) {
LinkedHashMap.Entry last = this.tail;
this.tail = p;
if (last == null) {
this.head = p;
} else {
p.before = last;
last.after = p;
}
}
下面是HashMap的put方法中的代码片段:
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null) {
e.value = value;
}
this.afterNodeAccess(e);
return oldValue;
}
其中调用了this.afterNodeAccess(e),在HashMap中这是一个空方法,LinkedHashMap中实现了这个方法如下 :
@Override
void afterNodeAccess(Node e) { // move node to last
LinkedHashMap.Entry last;
if (this.accessOrder && (last = this.tail) != e) {
LinkedHashMap.Entry p =
(LinkedHashMap.Entry) e;
LinkedHashMap.Entry b = p.before;
LinkedHashMap.Entry a = p.after;
p.after = null;
if (b == null) {
this.head = a;
} else {
b.after = a;
}
if (a != null) {
a.before = b;
} else {
last = b;
}
if (last == null) {
this.head = p;
} else {
p.before = last;
last.after = p;
}
this.tail = p;
++this.modCount;
}
}
从注释可以看出,将Node移动到链表尾部 , 并为LinkedHashMap.Entry的after和before赋值。
@Override
public V get(Object key) {
Node e;
if ((e = this.getNode(hash(key), key)) == null) {
return null;
}
if (this.accessOrder) {
// 详见3.2
this.afterNodeAccess(e);
}
return e.value;
}
如果设置了accessOrder为访问顺序,那么会把get到的Entry移动到尾部。