今天来分析一下JDK LinkedHashMap的源代码
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
可以看到,LinkedHashMap继承自HashMap,并且也实现了Map接口,所以LinkedHashMap沿用了HashMap的大多数方法
,包括构造方法也调用了父类HashMap的构造方法:
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
public LinkedHashMap() {
super();
accessOrder = false;
}
public LinkedHashMap(Map<? extends K, ? extends V> m) {
super(m);
accessOrder = false;
}
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
但是昨天在分析HashMap的时候说过HashMap的init方法没有实现,但是LinkedHaqshMap已经对其实现:
void init() {
header = new Entry<K,V>(-1, null, null, null);//初始化一个Entry类型的header
header.before = header.after = header;
}
在LinkedHashMap中多了一个accessOrder变量,他表示迭代时候的一个顺序,若为true,则按照读取顺序排序(读得越多越在前,也就最先被迭代),若为false
则按照插入顺序排序.从LinkedHaqshMap的前4个构造方法可以看出,accessOrder默认为false,故按照插入顺序进行排序.
public V get(Object key) {
Entry<K,V> e = (Entry<K,V>)getEntry(key);
if (e == null)
return null;
e.recordAccess(this);
return e.value;
}
在这个get方法中要注意recordAccess这个方法:
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
if (lm.accessOrder) {
lm.modCount++;
remove();
addBefore(lm.header);
}
}
这个方法定义在LinkedHashMap的内部类Entry中,他判断accessOrder属性,若为true,则执行一个叫做LRU的算法
该算法的中文名称叫做最近最少使用算法,他通过将刚访问的entry移除,然后加到header前面,这样迭代的时候会优先迭代
最近频繁访问的entry,从而就改变了迭代的顺序
对于put方法,LinkedHashMap也实现了父类HashMap没有实现的recordAccess,并重写了addEntry方法,虽然在LinkedHashMap没有重写put方法
void addEntry(int hash, K key, V value, int bucketIndex) {
createEntry(hash, key, value, bucketIndex);//在header前构造一个entry
Entry<K,V> eldest = header.after;//找到最老的一个元素
if (removeEldestEntry(eldest)) {
removeEntryForKey(eldest.key);
} else {
if (size >= threshold)
resize(2 * table.length);
}
}
可以看到该方法会删除最老的一个元素,removeEldestEntry是一个受保护的方法,用来确定是否满足删除条件,可以重写它实现自己的策略,默认该方法返回false