概述: LinkedHashMap 继承了 HashMap,所以还是应该注重 HashMap 的源码,本次只看不同的地方。 首先 LinkHashMap 在 entry 中维护了双链(before:指向前一个entry元素。after:指向后一个entry元素),所以 entry 需要改造多一个前指针、一个后指针。 put 操作整体没变,addEntry方法中的createEntry方法里加了个前后指针的实现,没啥太大东西。总结 :LinkedHashMap是HashMap的子类,实现的原理跟HashMap差不多,唯一的区别就是LinkedHashMap多了一个双向循环链表。 源码大致上就是在hashmap的基础上加了双链表操作。
LinkedHashMap 改造 hashMap 的地方:
- entry 改造篇: 为了维护双向链表
//before:指向前一个entry元素。after:指向后一个entry元素
Entry<K,V> before, after;
- put 篇:对 entry 部分需要操作双链表
// 整个 put 方法和 hashmap 几乎一样,就是 addEntry 重写
addEntry(hash, key, value, i);
// 重写的createEntry,这里要注意的是,新元素放桶中,是放第一位,而不是往后追加,所以下面方法中前面三行应该知道了
void createEntry(int hash, K key, V value, int bucketIndex) {
HashMap.Entry<K,V> old = table[bucketIndex];
Entry<K,V> e = new Entry<>(hash, key, value, old);
table[bucketIndex] = e;
// 这个方法的作用就是将e放在双向循环链表的末尾,需要将一些指向进行修改的操作。。
e.addBefore(header);
- get篇:linkedHashMap中有get方法,不会使用父类中的get方法
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;
}
// 如果accessOrder为true,那么就会用访问顺序。if条件下的语句会执行,作用就是将最近访问的元素放链表的末尾。
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
if (lm.accessOrder) {
lm.modCount++;
remove();
addBefore(lm.header);
}
}