《Java原始碼分析》 LinkedHashMap

2021-08-07 21:48:43 字數 4705 閱讀 3674

public

class

linkedhashmap

extends

hashmap

implements

map

從結構可以看出,linkedhashmap繼承hashmap並實現了map介面。

下面幾個是linkedhashmap的建構函式,每個建構函式都是直接呼叫父類hashmap的建構函式來完成相應的初始化工作。唯一的不同在於對變數:accessorder 指定為 false。

public

linkedhashmap(int initialcapacity, float loadfactor)

public

linkedhashmap(int initialcapacity)

public

linkedhashmap()

public

linkedhashmap(map<? extends k, ? extends v> m)

public

linkedhashmap(int initialcapacity,

float loadfactor,

boolean accessorder)

建構函式中所提到的accessorder

/**

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

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

**@serial

*/final

boolean accessorder;

根據注釋,理解如下:

accessorder,簡單說就是這個用來控制元素的順序, 

accessorder為true: 表示按照訪問的順序來,也就是誰最先訪問,就排在第一位 

accessorder為false表示按照存放順序來,就是你put元素的時候的順序。

entry類繼承的是hashmap.node類,且引入了兩個屬性before/after,hashmap就是利用hashmap.node類實現的單鏈表,再加上借助乙個儲存hashmap.node的陣列就實現了「陣列鍊錶」的結合體。而linkedhashmap引入before/after兩個屬性,可以看出,是準備實現雙向鍊錶的,因此linkedhashmap將是「陣列和雙鏈表」的結合體。

static

class

entry

extends

hashmap.node }

//下面為hashmap的node類

static

class

node

implements

map.entry

public

final k getkey()

public

final v getvalue()

public

final string tostring()

public

final

int hashcode()

public

final v setvalue(v newvalue)

public

final

boolean equals(object o)

return

false;

}}

既然是集合,肯定會有put方法來往容器中新增元素,在linkedhashmap搜尋了半天,沒有找到,在找put方法的過程中,發現有get方法,怎麼會沒有put方法呢??想了下,唯一的可能就是linkedhashmap繼承了hashmap沒有重寫hashmap中的put方法也。

下面我們貼出hashmap的put方法,看看這個put方法在linkedhashmap中是如何來工作的。

public v put(k key, v value) 

final v putval(int hash, k key, v value, boolean onlyifabsent,

boolean evict)

if (e.hash == hash &&

((k = e.key) == key || (key != null && key.equals(k))))

break;

p = e;}}

v oldvalue = e.value;

if (!onlyifabsent || oldvalue == null)

e.value = value;

//1------linkedhashmap

afternodeaccess(e);

return oldvalue;}}

++modcount;

if (++size > threshold)

resize();

//2、linkedhashmap

afternodeinsertion(evict);

return

null;

}

上面就是hashmap中put方法的**,在看linkedhashmap原始碼之前看hashmap的時候,看到put方法中呼叫afternodeaccess(e)和afternodeinsertion(evict);而這兩個方法在hashmap是兩個空實現的方法:

// callbacks to allow linkedhashmap post-actions

void afternodeaccess(nodep)

void afternodeinsertion(boolean evict)

當時,還在鬱悶,為什麼呼叫了兩個空實現的函式呢??

現在,看了linkedhashmap的原始碼,原來這兩個函式是專門給linkedhashmap重寫用的。只要linkedhashmap重寫了這兩個函式,也就完成了linkedhashmap自己的put方法實現。

put方法的思路在hashmap中已經分析過了,大致如下:根據key的hash值得到儲存位置,然後判斷該儲存位置是否已經有了元素,如果有了,則在該位置的鍊錶中,找是否含有該key,如果有該key,則更新value。如果沒有找到,則將節點插入到該位置的煉表頭。

現在,由於針對的是linkedhashmap,因此思路稍微發生了點變化,在鍊錶中找到key之後呼叫了afternodeaccess函式,linkedhashmap中的此函式不再為空,如果沒有找到key,在插入節點之後返回之前,呼叫了afternodeinsertion方法。

下面我們就來看下這兩個函式的具體內容。

afternodeaccess(node

void afternodeaccess(nodee) 

tail = p;

++modcount;

}}

下面介紹afternodeinsertion(boolean evict)

從原始碼中可以看到,這個函式相當於什麼都沒有做。

原因為:removeeldestentry函式一直返回false,導致這個函式afternodeinsertion的if條件也就一直為false。

因此,不知道這個函式為什麼這麼寫,分析了下,由於linkedhashmap當accessorder為false時,要按照新增元素的順序進行維護鍊錶,而hashmap就是直接將新節點放入到煉表頭,因此這個函式也就不需要做什麼了。

void afternodeinsertion(boolean evict) 

}protected

boolean

removeeldestentry(map.entryeldest)

以上就是關於linkedhashmap的put方法,

linkedhashmap與hashmap的區別真心不大,從put方法上可以看出,唯一的區別在於,如果我們設定了accessorder = true,則會將訪問的節點放入到鍊錶的尾結點處,其它的都一樣。

get方法的思路雖然對hashmap的get方法進行了重寫,但基本與hashmap的思路一致:也是直接呼叫getnode獲取到節點物件,然後返回其值。

但是,在linkedhashmap中,由於需要有順序需要維護,因此,當accessorder = true 時,則需要呼叫afternodeaccess(e)方法將此節點放到雙向鍊錶的末尾。而如果accessorder = false.則完全與hashmap類中的get方法一模一樣。

public v get(object key)
getordefault方法與get方法唯一的區別在於,如果key不存在,則返回預設值而不是返回null。

public v getordefault(object key, v defaultvalue)
linkedhashmap類中其它的方法基本與hashmap類中的方法差不多,這裡就不再進行介紹。

linkedhashmap 和hashmap 功能基本一樣,都是維護的鍵值對集合,連遍歷 以及方法都類似,唯一的區別在於hashmap 裡面的元素是根據hash值來決定存放位置的,是無序的,而linkedhashmap 維護的是乙個按順序存放的雙向鍊錶,是有序的。

因此,記住,他們的區別在於:linkedhashmap是「陣列和雙向鍊錶」的結合體,而hashmap是「陣列和單向鍊錶」的結合體就夠了。

java原始碼分析

在往佇列中插入資料由下面幾個函式,他們的區別就是對佇列滿的情況處理不同 put 一直等待著 offer 無時間 如果空了直接返回false offer 有時間 等待指定的時間,在指定時間內如果空了,那麼插入,負責返回false add 丟擲乙個illegalstateexception異常 首先來看...

Java原始碼分析之ArrayList

自我學習原始碼,也借鑑了網上其他的資料,有寫的不準確的地方,請輕噴,謝謝 1 繼承自abstractlist類 2 實現了randomaccess介面,randomaccess介面是list 實現所使用的標記介面,用來表明其支援快速 通常是固 定時間 隨機訪問。此介面的主要目的是允許一般的演算法更改...

java集合相關原始碼分析

hashmap 原始碼分析 hashset 原始碼分析 arraylist 原始碼分析 concurrentmap 原始碼分析 2018 03 25 map 綜述 一 徹頭徹尾理解 hashmap map 綜述 二 徹頭徹尾理解 linkedhashmap map 綜述 三 徹頭徹尾理解 concu...