Jdk1 8中的LinkHashMap實現原理

2021-07-25 13:51:17 字數 2884 閱讀 8942

linkedhashmap繼承自hashmap,是hash表和煉表的實現,並且依靠著雙向鍊錶保證了迭代順序是插入的順序。如果 乙個key重新插入到linkedhashmap中,那麼這個插入順序是無效的,也就是說,如果m.put(k,v)時,呼叫m.containskey(k),將會返回true,更新value值,但是順序不變。

public

class

testlinkhashmap }}

執行結果如下:

key=1 value=4

key=2 value=2

key=3 value=3

從上面的程式我們可以看見,同一key的多次插入,並不會影響其順序

迴圈雙向鍊錶的頭部存放的是最久訪問的節點或最先插入的節點,尾部為最近訪問的或最近插入的節點,迭代器遍歷方向是從鍊錶的頭部開始到鍊錶尾部結束,在鍊錶尾部有乙個空的header節點,該節點不存放key-value內容,為linkedhashmap類的成員屬性,迴圈雙向鍊錶的入口;

* 雙向鍊錶的頭部(eldest)

*/transient linkedhashmap.entryhead;

/*** 雙向鍊錶的尾部(youngest)

*/transient linkedhashmap.entrytail;

/***

*accessorder為true時,按訪問順序排序,false時,按插入順序排序

* */

final

boolean accessorder;

linkedhashmap的entry是繼承與node類,也就是linkedhashmap與hashmap的根本區別所在,node是鍊錶形式,只有next與下乙個元素進行連線,而entry的鍊錶有before和after兩個連線點。

static

class

entry

extends

hashmap.node }

區別是將節點變成entry,並且按照鍊錶方式將元素有序連線

nodenewnode(int hash, k key, v value, nodee)
afternodeaccess方法

void afternodeaccess(nodee) 

// 尾結點為p

tail = p;

// 增加結構性修改數量

++modcount;}}

就是說在進行put之後就算是對節點的訪問了,那麼這個時候就會更新鍊錶,把最近訪問的放到最後,保證鍊錶。關鍵引數是accessorder,這個引數只有在public linkedhashmap(int initialcapacity, float loadfactor,boolean accessorder) 中可以手動設定為true,其餘時候都預設為false

afternodeinsertion方法

void afternodeinsertion(boolean evict) 

}

如果使用者定義了removeeldestentry的規則,那麼便可以執行相應的移除操作

afternoderemoval方法

void afternoderemoval(nodee)
這個函式是在移除節點後呼叫的,就是將節點從雙向鍊錶中刪除。

我們從上面3個函式看出來,基本上都是為了保證雙向鍊錶中的節點次序或者雙向鍊錶容量所做的一些額外的事情,目的就是保持雙向鍊錶中節點的順序要從eldest到youngest。

removeeldestentry方法

在linkedhashmap中預設返回是false,當需要實現lru演算法的時候繼承linkedhashmap的子類重寫這個方法即可,accessorder 需要初始化為true

protected

boolean

removeeldestentry(map.entryeldest)

關於lru演算法的具體實現,可以參考這篇部落格基於linkedhashmap實現lru快取排程演算法原理及應用

get方法

put函式在linkedhashmap中未重新實現,而get函式則重新實現並加入了afternodeaccess來保證訪問順序,下面是get函式的具體實現:

public v get(object key)
這裡需要注意的是,如果accessorder為true時,那麼將會產生structural modification

官方描述是這樣的:

大致意思如下:對於 access-ordered模式來說,增加或者刪除操作,都會產生structural modification。在access-ordered模式下,會影響迭代順序。例如查詢map是呼叫get方法,就會產生structural modification。在insertion-ordered模式下,如果僅僅是修改乙個已經存在的key所對映的value,那麼不會產生structural modification。

linkhashmap繼承hashmap並且實現了map介面,它的entry繼承自hashmap的node,在entry裡增加了before和after,保證了鍊錶的有序。增加了head和tail,用於記錄雙向鍊錶的頭部和尾部。其中head在保留hashmap的查詢效率的同時,可以按照元素的插入順序進行遍歷,並提供了元素的lru訪問

jdk 1 8中的list排序

首先看看collections實現 public static void sort listlist,comparatorc public static extends comparable void sort listlist collections的實現可以看出,排序實現分為兩種 是否實現了co...

JDK1 8中的陣列排序

根據不同的情況,選擇不同的排序演算法。1 當需要排列的元素較少的時候,採用普通的插入排序 當被排序的陣列長度小於47但排序不是從陣列起始位置開始的時候,那麼就會選擇哨兵插入排序的方式進行排序。這種情況主要是當sort被雙基準快排遞迴呼叫的時候才會使用 2 如果元素較多,大於插入排序的閾值,但是小於歸...

jdk1 8常用總結

1.查詢集合裡的第乙個物件 filter 例 查詢listlist 中username為小明的物件t list.stream filter findfirst 1 list.stream filter e 小明 equals e.getusername findfirst 2.查詢滿足條件的物件,並...