基礎資料結構之LinkedHashMap原始碼分析
阿新 • • 發佈:2019-02-12
1.LinkedHashMap資料結構是雙向迴圈連結串列
LinkedHashMap節點中得知相關內容,Node節點中存在before,after,雙向連結串列特性
原始碼如下
/** * LinkedHashMap entry. */ private static class Entry<K,V> extends HashMap.Entry<K,V> { //These fields comprise the doubly linked list used for iteration. Entry<K,V> before, after; Entry(int hash, K key, V value, HashMap.Entry<K,V> next) { super(hash, key, value, next); }
e = header; e != header ;e = e.after 迴圈連結串列特性
原始碼如下:
public boolean containsValue(Object value) { // Overridden to take advantage of faster iterator if (value==null) { for (Entry e = header.after; e != header; e = e.after)//是否包含value,遍歷整個連結串列檢視元素是否存在 if (e.value==null) return true; } else { for (Entry e = header.after; e != header; e = e.after) if (value.equals(e.value)) return true; } return false; }
LinkedHashMap初始化原始碼如下:
/** * Called by superclass constructors and pseudoconstructors (clone, * readObject) before any entries are inserted into the map. Initializes * the chain. */ void init() { header = new Entry<K,V>(-1, null, null, null); header.before = header.after = header; //一個節點前驅指標和後繼指標都指向自己 }
2.LinkedHashMap新增新元素
/**
* This override alters behavior of superclass put method. It causes newly
* allocated entry to get inserted at the end of the linked list and
* removes the eldest entry if appropriate.
*/
void addEntry(int hash, K key, V value, int bucketIndex) {
createEntry(hash, key, value, bucketIndex);//陣列中索引放入元素 && 新元素插入到雙向迴圈連結串列中
// Remove eldest entry if instructed, else grow capacity if appropriate
Entry<K,V> eldest = header.after;
if (removeEldestEntry(eldest)) { //元素相同,移除old Entry元素
removeEntryForKey(eldest.key);
} else {
if (size >= threshold) //如果有效元素size > 擴容因子*size
resize(2 * table.length); //按照兩倍大小容量擴容
}
}
/**
* This override differs from addEntry in that it doesn't resize the
* table or remove the eldest entry.
*/
void createEntry(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);//建立一個新的Entry節點
table[bucketIndex] = e; //新的Entry節點,放入到table陣列中,table陣列是HashMap類的屬性
e.addBefore(header); //新的Entry節點,插入到雙向迴圈連結串列中
size++; //有效元素大小+1
}
3.LinkedHashMap獲取訪問元素特性
public V get(Object key) {
Entry<K,V> e = (Entry<K,V>)getEntry(key); //呼叫父類HashMap方法獲取元素
if (e == null)
return null;
e.recordAccess(this); //訪問後,對該訪問痕跡進行記錄,然後重新排序。從而實現LRU淘汰最久未使用的元素
return e.value;
}
/**
* 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.
*/
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
if (lm.accessOrder) { //如果打開了accessOrder開關
lm.modCount++; //訪問記錄modCount自增1
remove();
addBefore(lm.header); //訪問的元素,前面移動
}
}
優化後的程式碼
public V get(Object key) {
Entry<K,V> e = (Entry<K,V>)getEntry(key);
if (e == null)
return null;
if(e.accessOrder) //如果打開了accessOrder開關,進行排序。可以省略強制轉化的效率
e.recordAccess(this);
return e.value;
}
總結:
1.資料結構特性可以疊加使用。陣列特性增加連結串列特性,可以進行擴容元素屬性。