由淺入深解析HashMap系列二 擴容

2022-03-17 11:49:53 字數 2641 閱讀 3820

由淺入深解析hashmap系列一---hashmap簡單實現 增、刪、查。

前面簡單的實現了hashmap的增刪查功能,這一章節主要是介紹擴容(不考慮衝突),當陣列元素達到一定閾值時,需要擴容,擴容之後,需要對原來的陣列中的元素進行再次hash。在開始之前先介紹幾個概念:

初始容量:default_initial_capacity = 1 << 4。在jdk1.8中,預設的容量為16。在初始化hashmap時,並不會按照這個初始容量初始化陣列,而是在第乙個put元素時,才初始化陣列。

載入因子:default_load_factor = 0.75f ,雜湊表在其容量自動增加之前可以達到多滿的一種尺度。

閾值:threshold,等於capacity * load factor。比如說:初始時,初始容量為16,載入因子為0.75,則閾值為12。當雜湊表中的節點個數為12個時,就需要擴容。也許按照我們的思維習慣,當節點個數達到16時,才擴容。載入因子過低,如果擴容之後,不再有資料增加,增加了空間開銷;載入因子過高雖然減少了空間開銷,但同時也增加了查詢成本,所以需要對其有這個折中。

具體步驟如下:

1)獲取新的容量和閾值。根據old capacity,經過擴容演算法,獲取new capacity和threshold。擴容演算法:新的容量=原來的容量*2;新的閾值=原來的閾值*2;初始容量=16;初始閾值=初始容量*載入因子=16*0.75。

2)對原有陣列元素重新分布。前一章節提到過,下標index的獲取與陣列長度也就是capacity有關,通過上面獲取的新的capacity,重新計算節點下標,也就是對原有雜湊表中的元素再雜湊到新的雜湊表中。

注意:當原有容量已經達到最大容量時,就不允許再擴容,而是返回初始陣列。

1

/**2

* 1)獲取新的容量和閾值。

3* 2)對原有陣列進行再雜湊。

4* 注意:當原有容量已經達到最大容量時,就不允許再擴容,而是返回初始陣列。

5* 新的容量=原來的容量*2;新的閾值=原來的閾值*2;初始容量=16;初始閾值=初始容量*載入因子=16*0.756*

@return7*/

8final node resize()

22//

新的容量=舊的容量*2。新的閾值=舊的閾值*2

23else

if ((newcap = oldcap << 1) < maximum_capacity &&

24 oldcap >=default_initial_capacity)

25 newthr = oldthr << 1; //

double threshold

26 }//

舊的容量小於等於0時,若舊的閾值大於0,新的閾值舊等於舊的閾值。

27else

if (oldthr > 0) //

initial capacity was placed in threshold

28 newcap =oldthr;

29//

舊的容量小於等於0,舊的閾值小於等於0,新的容量和閾值都等於預設值。這一般是初次呼叫hashmap時觸發

30//

閾值=載入因子*初始容量=0.75*16=12。也就是當初次新增元素達到12個時,就擴容。

31else

35//

對閾值進行設計,臨界條件的判斷,不明白到這一步閾值為啥還會為0

36if (newthr == 0)

41//

設定閾值

42 threshold =newthr;

43//

初始化新的陣列,對原有的陣列進行再雜湊

44 node newtab = (node)new

node[newcap];

45 table =newtab;

46if (oldtab != null

) 54}55

}56return

newtab;

57 }

view code

1)判斷陣列(node table)是否為null或者長度為0。上節為了簡便在初始化hashmap時,構建乙個長度為100的陣列,而在這一章節中,初始化陣列的操作延遲到第一次新增元素的時候。故在put操作時,要判斷陣列的長度是不是為0或者為null。

2)當陣列中元素的個數達到給定閾值時,呼叫resize函式擴容。

1

/**2

* 新增。

3* 考慮擴容,但是不考慮衝突4*

@param

key5

* @param

value6*

@return7*/

8public

v put(k key, v value)

9

view code

只有在新增元素的時候,才需要考慮resize,在刪除、查詢時,不需要考慮,所以remove、get函式和上一章節是一樣的。

個人觀點:因resize導致重新hash,節點重新雜湊,故初始容量和載入因子的設定還是很重要的。

socket 由淺入深系列 原理(一)

來自 網路整理 個人覺得寫乙個網路應用程式沒有是一件非常easy的事。其實,我們剛開始的時候總覺得的原則 建立 連線套接字 接受乙個連線 傳送資料 而真正複雜編寫乙個網路應用程式的規模從乙個連線到成千上萬的連線!那麼本系列將對sockt由淺入深的介紹.msdn 詳細作用參考 socket 由淺入深 ...

HashMap深度解析

簡介 基於雜湊表的 map 介面的實現。此實現提供所有可選的對映操作,並允許使用 null 值和 null 鍵。除了非同步和允許使用 null 之外,hashmap 類與 hashtable 大致相同。此類不保證對映的順序,特別是它不保證該順序恆久不變。此實現假定雜湊函式將元素適當地分布在各桶之間,...

HashMap初步解析

hashmap集合 1 hashmap集合底層是雜湊表 雜湊表的資料結構。2 雜湊表是乙個怎樣的資料結構呢?雜湊表是乙個陣列和單向鍊錶的結合體。陣列 在查詢方面效率很高,隨機增刪方面效率很低。單向鍊錶 在隨機增刪方面效率較高,在查詢方面效率很低。雜湊表將以上的兩種資料結構融合在一起,充分發揮它們各自...