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...