LinkedHashMap如何保證有序

2021-10-19 13:38:37 字數 2350 閱讀 6649

我們常說linkedhashmap是有序的,這個有序也是分為兩種的,分別是:插入順序和訪問順序,我們可以通俗的認為:linkedhashmap = hashmap + 雙向鍊錶

以下的學習是基於jdk8

根據linkedhashmap的結構來看,是依賴於hashmap的,通過檢視原始碼,我們也會發現,linkedhashmap只是維護了乙個鍊錶,並沒有put、remove方法的具體實現,因為linkedhashmap的設計思想是:對資料的操作,是依賴於hashmap中的方法,只是在其中的一些細節方法,linkedhashmap會進行擴充套件,接下來我們先說屬性有哪些

/**

* the head (eldest) of the doubly linked list.

* 鍊錶的head節點

*/transient linkedhashmap.entry

head;

/** * the tail (youngest) of the doubly linked list.

* 鍊錶的尾結點

*/transient linkedhashmap.entry

tail;

/** * the iteration ordering method for this linked hash map: true

* for access-order, false for insertion-order.

* false:表示插入順序;true表示讀取順序

* @serial

*/final

boolean accessorder;

該屬性是來區分當前linkedhashmap是按照訪問順序排序,還是按照put順序有序,當該引數為true的時候,表示按照讀取順序有序;預設為false,按照put順序有序

在呼叫put方法的時候,會呼叫父類hashmap的put方法,那linkedhashmap如何維護節點之間的順序呢?

在put方法中,如果得到當前key要儲存的位置,會呼叫newnode()方法,初始化乙個node節點,

linkedhashmap對該方法,進行了覆寫,

/**

* 在向map中put元素的時候,是會初始化乙個node節點,如果是linkedhashmap,呼叫的是該方法

* 在該方法中,可以看到,會初始化乙個linkedhashmap.entry節點,然後將該節點插入到linkedhashmap的雙向鍊錶中

* 預設是加到鍊錶尾部

* @param hash

* @param key

* @param value

* @param e

* @return

*/node

newnode

(int hash, k key, v value, node

e)

這裡可以看到,除了初始化乙個節點之外,還會呼叫linknodelast方法,在linkednodelast方法中,會將p節點新增到自己維護的雙向鍊錶的尾部

/**

* 這是加入到鍊錶尾部的方法

* 如果當前是第乙個put的元素,那p就是head,否則,就把節點放到tail的後面

* @param p

*/private

void

linknodelast

(linkedhashmap.entry

p)}

假如在初始化linkedhashmap物件的時候,指定accessorder為true,那表示按照訪問順序有序,在get方法中,會對訪問到的元素進行處理

public v get

(object key)

這裡可以看到,如果是按照訪問順序有序的話,會額外呼叫afternodeaccess()方法,如果為false,會直接返回獲取到的節點value值,afternodeaccess方法簡單而言,就是將e節點移到鍊錶的尾部,所以,我們可以認為,最近訪問的在元素在鍊錶的最後面

所以:對於按照put順序有序的設定,在put元素的時候,本身就會把最新插入的元素放入到鍊錶的尾部,如果是按照訪問順序有序的話,在get的時候,會把訪問的元素移到鍊錶的尾部,根據該特點,也可以實現乙個簡單的lru演算法

對於hashmap和linkedhashmap來說,最大的區別就是:hashmap是無序的,linkedhashmap自己維護了節點的順序

LinkedHashMap是如何組織資料的

linkedhashmap繼承自hashmap,底層仍然是陣列加鍊表,除了發生衝突後的單鏈表,它還維護了乙個鏈結所有元素的雙鏈表,這樣就能記錄元素的插入或者訪問順序了。所以linkedhashmap可以做到有序迭代,也可以作為lru演算法的基石。linkedentryheader static cl...

LinkedHashMap 是如何實現的

linkedhash 底層基於 hashmap 實現並擴充套件了 hashmap.node 使其支援雙向鍊錶 示例 hashmaphashmap new hashmap linkedhashmaplinkedhashmap new linkedhashmap for int i 0 i 10 i s...

LinkedHashMap簡單解析

原始碼版本1.7 本文參考 1 內部結構 節點的結構 整體結構 插入過程 1 從table的角度看,新的entry需要插入到對應的bucket裡,當有雜湊衝突時,採用頭插法將新的entry插入到衝突鍊錶的頭部。2 從header的角度看,新的entry需要插入到雙向鍊錶的尾部。刪除過程 1 從tab...