Hashtable擴容,原始碼閱讀

2021-10-20 01:50:39 字數 3180 閱讀 5104

這篇文章,是筆者學習hash原始碼的筆記,寫作的過程,利於知識梳理,找到盲區。將會分三篇文章。

這是第一篇,講解hashtable擴容。雖然hashtable已經被concurrenthashmap取代了,但是原始碼簡單,利於我們理解hash的實現方式。

hashtable表結構。陣列+元素節點是單鏈表。

預設陣列長度是11,負載因子是0.75

/**

* constructs a new, empty hashtable with a default initial capacity (11)

* and load factor (0.75).

*/public

hashtable()

可以手動指定。為什麼hashmap的初始化是16,hashtable是11?原因是hashmap做了優化,後面hashmap篇講解。

hashtable擴容,元素數量達到閾值。閾值的計算。陣列長度 * 負載因子

threshold =

(int

)math.

min(initialcapacity * loadfactor, max_array_size +1)

;

預設的hashtable,當插入第9個元素時候,會擴容。測試**如下

public

class

hashtabletest

private

static object getvalue

(class c1

, object o, string field)

throws nosuchfieldexception, illegalacces***ception }18

:00:55.288

[main] info com.austin.daily.hashmap.hashtabletest -

11

public

static

void

main

(string[

] args)

throws nosuchfieldexception, illegalacces***ception

info com.austin.daily.hashmap.hashtabletest -

23

private

void

addentry

(int hash, k key, v value,

int index)

// creates the new entry.

@suppresswarnings

("unchecked"

) entry

e =(entry

) tab[index]

; tab[index]

=new

entry

<

>

(hash, key, value, e)

; count++

;}

新增entry前,先判斷達到threshold,核心**在rehash()

protected

void

rehash()

//建立乙個新hash陣列

entry,

?>

newmap =

newentry

,?>

[newcapacity]

;//與併發操作鎖有關係,待後續了解

modcount++

;//計算新的閾值

threshold =

(int

)math.

min(newcapacity * loadfactor, max_array_size +1)

;//替換為新的陣列

table = newmap;

//核心中的核心 迴圈old hash表的所有element(element是單鏈表的head)

for(

int i = oldcapacity ; i--

>0;)}}

每行**都有注釋。至此。已經解析完擴容機制。

我注意到。put()方法是頭插法,rehash()也是頭插法。會導致rehash後,插入順序會逆轉。下面是**驗證

@slf4j

public

class

hashtabletest

system.out.

println(""

);system.out.

println

("擴容後");

//擴容後

table.

put(

newkk()

,8);

entries =

(map.entry)

getvalue

(hashtable.

class

, table,

"table");

entry = entries[1]

;while

(entry != null)

}private

static object getvalue

(class c1

, object o, string field)

throws nosuchfieldexception, illegalacces***ception

}classkk}

7,6,

5,4,

3,2,

1,0,

擴容後8,0

,1,2

,3,4

,5,6

,7,process finished with exit code 0

建立類kk,覆蓋hashcode,使得element一定會在陣列索引1。列印的是table[1]的單鏈表元素順序。

觀察擴容前,頭插法,所以在前面;

擴容中,驗證後,果然是和倒置插入順序。8在最前面的原因是,會先處理原有element,再使用頭插法。

Vector和Hashtable原始碼閱讀與理解

vector是執行緒安全的arraylist public synchronized void insertelementat e obj,int index ensurecapacityhelper elementcount 1 system.arraycopy elementdata,index...

SynchronousQueue原始碼閱讀心得

synchronousqueue 簡寫為sq 同步佇列中,讀執行緒與寫執行緒只有相互匹配時才能完成一次完整的讀寫操作。而讀與寫的匹配依賴於transferqueue或transferstack中的transfer sq中重要的資料結構有transferqueue和transferstack,還有qn...

原始碼剖析 Hashtable 原始碼剖析

hashtable同樣是基於雜湊表實現的,同樣每個元素都是key value對,其內部也是通過單鏈表解決衝突問題,容量不足 超過了閾值 時,同樣會自動增長。hashtable也是jdk1.0引入的類,是執行緒安全的,能用於多執行緒環境中。hashtable同樣實現了serializable介面,它支...