Java 集合系列(四)LinkedHashMap 實現(xiàn)原理

LinkedHashMap 實現(xiàn)原理

集合

1. LinkedHashMap 概述

????????LinkedHashMap 是 Map 接口的哈希表和鏈接列表實現(xiàn)称近,具有可預知的迭代順序。此實現(xiàn)提供所有可選的映射操作仆百,并允許使用null 值和 null 鍵。此類不保證映射的順序,特別是它不保證該順序恒久不變。

????????LinkedHashMap 實現(xiàn)與 HashMap 的不同之處在于辫诅,后者維護著一個運行于所有條目的雙重鏈接列表。此鏈接列表定義了迭代順序涧狮,該迭代順序可以是插入順序或者是訪問順序炕矮。

????????注意,此實現(xiàn)不是同步的者冤。如果多個線程同時訪問鏈接的哈希映射肤视,而其中至少一個線程從結(jié)構(gòu)上修改了該映射,則它必須保持外部同步譬嚣。

2. LinkedHashMap 的實現(xiàn)

????????對于 LinkedHashMap 而言钢颂,它繼承與 HashMap钞它、底層使用哈希表與雙向鏈表來保存所有元素拜银。其基本操作與父類HashMap 相似,它通過重寫父類相關(guān)的方法遭垛,來實現(xiàn)自己的鏈接列表特性尼桶。下面我們來分析LinkedHashMap 的源代碼。

1) Entry 元素

????????LinkedHashMap 采用的 hash 算法和 HashMap 相同锯仪,但是它重新定義了數(shù)組中保存的元素Entry泵督,該 Entry 除了保存當前對象的引用外,還保存了其上一個元素 before 和下一個元素after 的引用庶喜,從而在哈希表的基礎上又構(gòu)成了雙向鏈接列表小腊。看源代碼:

2) 初始化

????????通過源代碼可以看出久窟,在 LinkedHashMap 的構(gòu)造方法中秩冈,實際調(diào)用了父類 HashMap的相關(guān)構(gòu)造方法來構(gòu)造一個底層存放的 table 數(shù)組。 如:

? ? ?HashMap 中的相關(guān)構(gòu)造方法:

????????我們已經(jīng)知道 LinkedHashMap 的 Entry 元素繼承 HashMap 的 Entry斥扛,提供了雙向鏈表的功能入问。在上述HashMap 的構(gòu)造器中,最后會調(diào)用init()方法,進行相關(guān)的初始化芬失,這個方法在 HashMap 的實現(xiàn)中并無意義楣黍,只是提供給子類實現(xiàn)相關(guān)的初始化調(diào)用。

????????LinkedHashMap 重寫了 init()方法棱烂,在調(diào)用父類的構(gòu)造方法完成構(gòu)造后租漂,進一步實現(xiàn)了對其元素Entry 的初始化操作。

3) 存儲

????????LinkedHashMap 并未重寫父類 HashMap 的 put 方法颊糜,而是重寫了父類 HashMap 的put 方法調(diào)用的子方法 void addEntry(int hash, K key, V value, int bucketIndex) 和 voidcreateEntry(int hash, K key, V value, int bucketIndex)窜锯,提供了自己特有的雙向鏈接列表的實現(xiàn)。

4) 讀取

????????LinkedHashMap 重寫了父類 HashMap 的 get 方法芭析,實際在調(diào)用父類 getEntry()方法取得查找的元素后锚扎,再判斷當排序模式accessOrder 為 true 時,記錄訪問順序馁启,將最新訪問的元素添加到雙向鏈表的表頭驾孔,并從原來的位置刪除。由于的鏈表的增加惯疙、刪除操作是常量級的翠勉,故并不會帶來性能的損失。

5) 排序模式

????????LinkedHashMap 定義了排序模式 accessOrder霉颠,該屬性為 boolean 型變量对碌,對于訪問順序,為true蒿偎;對于插入順序朽们,則為 false。

??private final boolean accessOrder;

????????一般情況下诉位,不必指定排序模式骑脱,其迭代順序即為默認為插入順序〔钥罚看 LinkedHashMap的構(gòu)造方法叁丧,如:

public LinkedHashMap(int initialCapacity, float loadFactor) {

????super(initialCapacity, loadFactor);

? ? ?accessOrder = false;

?}

????????這些構(gòu)造方法都會默認指定排序模式為插入順序。如果你想構(gòu)造一個 LinkedHashMap岳瞭,并打算按從近期訪問最少到近期訪問最多的順序(即訪問順序)來保存元素拥娄,那么請使用下面的構(gòu)造方法構(gòu)造LinkedHashMap:

public LinkedHashMap(int initialCapacity,

????float loadFactor,

????boolean accessOrder) {

????super(initialCapacity, loadFactor);

????this.accessOrder = accessOrder;

}

????????該哈希映射的迭代順序就是最后訪問其條目的順序,這種映射很適合構(gòu)建 LRU 緩存瞳筏。LinkedHashMap 提供了 removeEldestEntry(Map.Entry<K,V> eldest)方法稚瘾,在將新條目插入到映射后,put 和 putAll 將調(diào)用此方法乏矾。該方法可以提供在每次添加新條目時移除最舊條目的實現(xiàn)程序孟抗,默認返回false迁杨,這樣,此映射的行為將類似于正常映射凄硼,即永遠不能移除最舊的元素铅协。

protected boolean removeEldestEntry(Map.Entry eldest) {

????return false;

}

????????此方法通常不以任何方式修改映射,相反允許映射在其返回值的指引下進行自我修改摊沉。如果用此映射構(gòu)建LRU 緩存狐史,則非常方便,它允許映射通過刪除舊條目來減少內(nèi)存損耗说墨。例如:重寫此方法骏全,維持此映射只保存100 個條目的穩(wěn)定狀態(tài),在每次添加新條目時刪除最舊的條目尼斧。

private static final int MAX_ENTRIES = 100;

????protected boolean removeEldestEntry(Map.Entry eldest) {

????return size() > MAX_ENTRIES;

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末姜贡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子棺棵,更是在濱河造成了極大的恐慌楼咳,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烛恤,死亡現(xiàn)場離奇詭異母怜,居然都是意外死亡,警方通過查閱死者的電腦和手機缚柏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門苹熏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人币喧,你說我怎么就攤上這事轨域。” “怎么了粱锐?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵疙挺,是天一觀的道長。 經(jīng)常有香客問我怜浅,道長,這世上最難降的妖魔是什么蔬崩? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任恶座,我火速辦了婚禮,結(jié)果婚禮上沥阳,老公的妹妹穿的比我還像新娘跨琳。我一直安慰自己,他們只是感情好桐罕,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布脉让。 她就那樣靜靜地躺著桂敛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪溅潜。 梳的紋絲不亂的頭發(fā)上术唬,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機與錄音滚澜,去河邊找鬼粗仓。 笑死,一個胖子當著我的面吹牛设捐,可吹牛的內(nèi)容都是我干的借浊。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼萝招,長吁一口氣:“原來是場噩夢啊……” “哼蚂斤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起槐沼,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤橡淆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后母赵,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逸爵,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年凹嘲,在試婚紗的時候發(fā)現(xiàn)自己被綠了师倔。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡周蹭,死狀恐怖趋艘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凶朗,我是刑警寧澤瓷胧,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站棚愤,受9級特大地震影響搓萧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宛畦,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一瘸洛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧次和,春花似錦反肋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽罕邀。三九已至,卻和暖如春养距,著一層夾襖步出監(jiān)牢的瞬間诉探,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工铃在, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留阵具,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓定铜,卻偏偏與公主長得像阳液,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子揣炕,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350