hashmap的實現原理 陣列 entry

2021-08-20 04:09:43 字數 3401 閱讀 9042

hashmap在日常工作中使用場景非常多,程式設計師都知道是hashmap是執行緒非安全的,但是底層是以什麼方式儲存的?本人仔細研讀了一下原始碼,也只是掌握了核心的儲存功能,並沒有把全部**看明白,但是對於理解hashmap的儲存結構完全夠了。

儲存結構

hashmap底層是以陣列方式進行儲存。將key-value對作為陣列中的乙個元素進行儲存。

key-value都是map.entry中的屬性。其中將key的值進行hash之後進行儲存,即每乙個key都是計算hash值,然後再儲存。每乙個hash值對應乙個陣列下標,陣列下標是根據hash值和陣列長度計算得來。

由於不能的key有可能hash值相同,即該位置的陣列中的元素出現兩個,對於這種情況,hashmap採用鍊錶形式進行儲存。

下圖描述了hashmap的儲存結構圖

entry結構分析

entry是hashmap中封裝key-value鍵值對的,主要包括如下屬性

static

class entryimplements map.entry

public

final

k getkey

() public

final

v getvalue

() // 同乙個key時,新值替換舊值,返回舊值

public

final

v setvalue

(v newvalue)

// key值重寫equals方法

public

final

boolean

equals

(object o)

return

false

; }

// 重寫hashcode值

public

final

inthashcode

() public

final

string tostring

() // 其他方法省略

}

hashmap屬性分析hashmap的屬性分析

public class

hashmap

,v>

extends

abstractmapimplements map, cloneable, serializable

; /**

* 最開始時,hashmap是乙個空陣列。

*/transient entry table = (entry) empty_table;

/*** map的元素的個數

*/transient int size;

/** hashmap的實際儲存空間大小。這個空間是總空間*載入因子得出的大小。

* 比如預設是16,載入因子是0.74。則threshold就是12。

*/int threshold;

/*** 載入因子,即使用空間達到總空間的0.75時,需要擴容。

*/final

float loadfactor;

/***

*/transient int modcount;

/*** threshold這個值的最大值就是integer.max_value

*/static final

int alternative_hashing_threshold_default = integer.max_value;

put方法put(key,value)方法是hashmap中最重要的方法,使用hashmap最主要的就是使用put,get兩個方法。put方法底層儲存又是什麼呢,我們可以從put方法的原始碼進行分析

public

v put

(k key, v value)

// 如果key為null,則將null放入元素的第乙個位置

if(key == null

) return

putfornullkey(value);

// 計算key的hash值

inthash = hash(key);

// 根據key的hash值,陣列長度計算該entry的陣列下標

inti = indexfor(hash, table.length);

/****如果當前key的已經存在於map中,則將新值替換成舊值。

**/for

(entrye = table[i]; e != null

; e = e.next)

}// 如果是新的key需要儲存,則增加操作次數modcount++

modcount++;

// 將新增key-value鍵值對新增中map中。

addentry(hash, key, value, i);

return

null

; }

addentry方法addentry方法是將新增的key-value鍵值對存入到map中。該方法主要完成兩個功能:

1.1. 新增新元素前, 判斷是否需要對map的陣列進行擴容,如果需要擴容,則擴容空間大小是多少?

1.2. 對於新增key-value鍵值對,如果key的hash值相同,則構造單向列表。

從原始碼分析結果如下:

/**

** hash:key的hash值

** key:儲存的鍵

** value:儲存的value物件值

*** bucketindex:陣列下標位置,即key-value在陣列中的位置。

**/void

addentry(int

hash, k key, v value, int

bucketindex)

// 往陣列中新增新的key-value鍵值對

createentry(hash, key, value, bucketindex);

}

createentry該方法主要完成兩個功能,第一是新增新的key到entry陣列中,第二就是對於不同key的hash值相同的情況下,在同乙個陣列下標處,構建單向鍊錶進行儲存。

void

createentry(int

hash, k key, v value

, int

bucketindex)

HashMap的實現原理

一。hashmap的資料結構 資料結構中有陣列和鍊錶來實現對資料的儲存,但這兩者基本上是兩個極端。陣列 陣列儲存區間是連續的,占用記憶體嚴重,故空間複雜的很大。但陣列的二分查詢時間複雜度小,為o 1 陣列的特點是 定址容易,插入和刪除困難 鍊錶 鍊錶儲存區間離散,占用記憶體比較寬鬆,故空間複雜度很小...

HashMap實現原理

hashmap 的get 方法 呼叫get方法返回entry public v get object key getentry方法 final entrygetentry object key 對key int hash key null 0 hash key for entrye table in...

HashMap實現原理

資料結構中有陣列和鍊錶來實現對資料的儲存,但這兩者基本上是兩個極端。陣列儲存區間是連續的,占用記憶體嚴重,故空間複雜的很大。但陣列的二分查詢時間複雜度小,為o 1 陣列的特點是 定址容易,插入和刪除困難 鍊錶儲存區間離散,占用記憶體比較寬鬆,故空間複雜度很小,但時間複雜度很大,達o n 鍊錶的特點是...