1. 程式人生 > >HashMap,LinkedHashMap與TreeMap

HashMap,LinkedHashMap與TreeMap

HashMap:

基於Map介面實現,允許null值,非同步,不保證有序,也不保證不隨時間變化。
在HashMap中有兩個很重要的引數,容量(Capacity)和負載因子(Load factor)。
容量(Capacity)就是bucket的大小,負載因子(Load factor)就是bucket填滿程度的最大比例。

HashMap中put函式的實現:
1.對key的hashCode做hash,然後再計算index。
2.如果沒有碰撞直接放到bucket裡。
3.如果碰撞了,以連結串列形式存放在bucket後。
4.如果碰撞導致連結串列過長,就把連結串列轉換成紅黑樹。
5.如果節點已經存在就替換old value(保證key的唯一性)。
6.如果bucket滿了,(超過(load factor*current capacity)就要resize。

HashMap中get函式的實現:
1.當呼叫get方法時會呼叫hash函式,這個hash函式會將key的hashCode值返回,返回的hashCode與Entry陣列長度-1進行邏輯與運算得到一個index值,用這個index值來確定資料儲存在Entry陣列當中的位置。
2.通過迴圈來遍歷索引位置對應的連結串列,初始值為資料儲存在Entry陣列當中的位置,迴圈條件為Entry物件不為null,改變迴圈條件為Entry物件的下一個節點。
3.如果hash函式得到的hash值與Entry物件當中key的hash值相等,並且Entry物件當中的key值與get方法傳進來的key值equals相同則返回該Entry物件的value值,否則返回null。

RESIZE的實現:
當put時,如果目前的bucket佔用程度已經超過了Load Factor所希望的比例,就會發生resize。resize過程就是把bucket擴充為2倍,之後重新計算index,把節點再放到新的bucket中。

必須知道的:
1.什麼時候使用HashMap?他有什麼特點?
HashMap是基於Nap介面的實現,儲存鍵值對時,他可以接收null的值,是非同步的。HashMap儲存著Entry(hash,key,value,next)物件。

2.HashMap的工作原理?
通過hash的方法,通過put和get儲存和獲取物件。在儲存物件時,我們將key/value傳給put方法,他呼叫hashCode計算hash從而得到bucket位置進一步儲存。HashMap會根據當前bucket的佔用情況自動調整容量。獲取物件時,將key傳給get,他呼叫hashCode計算hash從而得到bucket位置,並進一步呼叫equils()方法確定鍵值對。如果發生碰撞時,HashMap通過連結串列將產生碰撞衝突的元素組織起來。在Java 8中,如果一個bucket中碰撞衝突元素超過某個限制(預設是8個),則使用紅黑樹來替換連結串列,從而提高速度。

3.你知道get,put的·原理嗎?equils()和hashCode()有什麼用?
通過對key的hashCode()進行hash,並記算下標,從而獲得buckets的位置,如果產生碰撞,則利用key.equils()方法去連結串列或樹中查詢對應的節點。

LinkedHashMap:

LinkedHashMap是hash表和連結串列的實現,並且依靠著雙向連結串列保證了迭代順序是插入的順序。

三個重點實現的函式:
LinkedHashMap繼承自HashMap,因此也重新實現了3個函式,其作用分別是:節點後訪問,節點後插入,節點移除後做一些事情。
**afterNodeAccess函式:**在進行put之後就算是對節點的訪問了,這個時候就會更新連結串列,把最近訪問的放到最後,保證連結串列。
afterNodeInsertion函式:
如果使用者定義了removeEldestEntry的規則,那麼便可以執行相應的移除操作。
afterNodeRemoval函式:
這個函式是在移除節點後呼叫的,就是將節點從雙向連結串列中刪除。

TreeMap:

HashMap不保證資料有序,LinkedHashMap保證資料可以保持插入順序,而如果我們希望Map可以保持key的大小順序的時候,我們就需要利用TreeMap。

put函式:將指定值與此對映中的指定鍵相關聯。如果對映以前包含鍵的對映,則將替換舊值。
get函式:get函式則相對來說比較簡單,以log(n)的複雜度進行get。
successor後繼:
怎麼理解這個successor呢?只要記住,這個是中序遍歷就好了,L-D-R。具體細節如下:
a. 空節點,沒有後繼
b. 有右子樹的節點,後繼就是右子樹的“最左節點”
c. 無右子樹的節點,後繼就是該節點所在左子樹的第一個祖先節點