/** * Called by superclass constructors and pseudoconstructors (clone, * readObject) before any entries are inserted into the map. Initializes * the chain. */ @Override voidinit(){ header = new Entry<>(-1, null, null, null); header.before = header.after = header; }
put方法
LinkedHashMap 并未重写父类 HashMap 的 put 方法,而是重写了父类 HashMap 的 put 方法调用的子方法: void recordAccess(HashMap m)void addEntry(int hash, K key, V value, int bucketIndex)void createEntry(int hash, K key, V value, int bucketIndex) 提供了自己特有的双向链接列表的实现。我们在之前的文章中已经讲解了HashMap的put方法,我们在这里重新贴一下 HashMap 的 put 方法的源代码:
/** * This method is invoked by the superclass whenever the value * of a pre-existing entry is read by Map.get or modified by Map.set. * If the enclosing Map is access-ordered, it moves the entry * to the end of the list; otherwise, it does nothing. */ //记录访问顺序 voidrecordAccess(HashMap<K,V> m){ LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m; if (lm.accessOrder) { lm.modCount++; remove(); addBefore(lm.header); // 将当前访问的对象插入到header之前 } }
voidaddEntry(int hash, K key, V value, int bucketIndex){ // 调用create方法,将新元素以双向链表的的形式加入到映射中。 createEntry(hash, key, value, bucketIndex);
// 删除eldest元素 Entry<K,V> eldest = header.after; //如果有必要移除最老的节点,那么就移除。LinkedHashMap默认removeEldestEntry总是返回false //也就是这里if里面的语句永远不会执行 //这里removeEldestEntry主要是给LinkedHashMap的子类留下的一个钩子 //子类完全可以根据自己的需要重写removeEldestEntry,后面我会举个现实中的例子🌰 if (removeEldestEntry(eldest)) { removeEntryForKey(eldest.key); } else { if (size >= threshold) resize(2 * table.length); } } // 在新建节点之后调用 addBefore 方法将新添加的节点放在header之前 voidcreateEntry(int hash, K key, V value, int bucketIndex){ HashMap.Entry<K,V> old = table[bucketIndex]; Entry<K,V> e = new Entry<K,V>(hash, key, value, old); table[bucketIndex] = e; // 调用元素的addBrefore方法,将元素e加入到header之前 e.addBefore(header); size++; }
/** * Inserts this entry before the specified existing entry in the list. */ // 将this添加到existingEntry之前 privatevoidaddBefore(Entry<K,V> existingEntry){ after = existingEntry; before = existingEntry.before; before.after = this; after.before = this; }
/** * Removes this entry from the linked list. */ //删除一个节点时,需要把 //1. 前继节点的后继指针 指向 要删除节点的后继节点 //2. 后继节点的前继指针 指向 要删除节点的前继节点 privatevoidremove(){ before.after = after; after.before = before; }
public V get(Object key){ // 调用父类HashMap的getEntry()方法,取得要查找的元素。 Entry<K,V> e = (Entry<K,V>)getEntry(key); if (e == null) returnnull; // 记录访问顺序。 e.recordAccess(this); return e.value; }