HashMap 和 HashTable 的區別

2021-08-15 12:06:04 字數 3667 閱讀 8069

hashmap 和 hashtable 的區別

1、hashmap 是非執行緒安全的,hashtable 是執行緒安全的。

2、hashmap 的鍵和值都允許有 null 值存在,而 hashtable 則不行。

3、因為執行緒安全的問題,hashmap 效率比 hashtable 的要高。

hashmap put 方法的內部儲存結構(jdk 1.7)

1、hashmaphashmap = new hashmap(); 的時候會通過建構函式初始化 map 的大小和擴容因子。

public hashmap() 

public hashmap(int initialcapacity , float loadfactor)

2、map 的初始化大小和擴容因子設定完成之後,map 準備就緒,呼叫 map.put() 方法向 map 中新增元素。在 put 方法中,如果當前 table(也就是 entry 陣列),就在 inflatetable 方法中初始化 table,

public v put(k key, v value ) 

...

return null;

}

3、在 inflatetable 方法中通過 rounduptopowerof2 方法計算當前要初始化的大小是否大於等於 maximum_capacity(2的 30次方),如果大於等於就設定成 maximum_capacity 的值,不大於就呼叫 integer.highestonebit 方法計算初始化的大小。

highestonebit 方法簡單的說就是:

3.1、如果乙個數是0, 則返回0;

3.2、如果是負數, 則返回 -2147483648;

3.3、如果是正數, 返回的則是跟它最靠近的比它小的2的n次方;例如:17 則返回 16;15 則返回 8;

private void inflatetable(int tosize) 

private static int rounduptopowerof2( int number )

4、初始化完成之後再回到 put 方法中,往下看會看到判斷 key 值是否是空值,當 key 是空值的時候,呼叫 putfornullkey 處理。首先取出下標為0的元素,如果當前元素是空元素,就將當前key的 hashcode 設定為0,放在 table 下標為 0 的位置。

public v put(k key, v value) 

private v putfornullkey(v value)

}modcount++;

addentry(0, null, value , 0);

return null;

}

5、如果不是空的key,先計算 key 的 hash 值,然後呼叫 indexfor 方法根據 hash 值和 table 的長度計算出當前的 key 儲存在 table 中的位置 i 。計算完位置之後,再取出位置 i 處是否已經有資料,如果有資料並且資料中也有相同的 hash key 值的時候,就將當前的值替換掉舊的值並返回舊的值。迴圈完之後沒有相同的 hash key 值,就呼叫 addentry 方法向 table 位置 i 處新增元素。新增規則是將當前 key 存放在位置 i 處鍊錶的最頂部。

public v put(k key, v value) 

}modcount++;

addentry(hash, key , value, i);

return null;

}

6、新增的時候判斷當前位置 i 是否已經大於要擴容的極限(總長度 x 擴容因子),擴容是當前 table 大小的 2 倍。擴容之後重新"雜湊掩碼值 ",然後迴圈舊 table,將每乙個元素都重新計算儲存在擴容之後新 table 中的哪個位置上。轉換完之後,再計算下次要擴容的極限大小是多少。

void addentry(int hash , k key, v value, int bucketindex) 

createentry(hash, key, value, bucketindex);

}void resize(int newcapacity )

entry newtable = new entry[newcapacity];

transfer(newtable, inithashseedasneeded(newcapacity));

table = newtable ;

threshold = (int)math.min(newcapacity * loadfactor, maximum_capacity + 1);

}void transfer(entry newtable, boolean rehash)

int i = indexfor (e.hash, newcapacity);

e.next = newtable[i];

newtable[i] = e;

e = next ;}}

}

hashmap get 方法的內部儲存結構(jdk 1.7)

1、get 方法比較簡單,進來之後先判斷是否 key 是否是 null,是 null 就特殊處理,不是就常規處理並返回這個 key 對應的值。v 是泛型,宣告 hashmap 的時候中的 value 型別。

public v get(object key)

2、當 key 是 null  的情況,先判斷當前 table 的 size 是否大於 0,大於 0 就繼續,否則返回 null。然後再直接獲取 hashmap 中 table(entry) 下標為 0 的位置的鍊錶,迴圈這個鍊錶,依次判斷每個元素的 key 是否為 null,為 null 就返回對應的值。

private v getfornullkey() 

for (entrye = table[0]; e != null; e = e.next)

return null;

}

3、key 不為 null 的情況,同樣是先判斷當前 table 的 size 是否大於 0,大於 0 就繼續,否則返回 null。然後再計算要查詢 key 的 hash 碼,通過 hash 碼和 table 的長度計算出這個 key 對應 table 的下標,得到下標之後取出 hashmap 中對應下標的 table(entry) 鍊錶,迴圈這個鍊錶,依次判斷每個元素的 key 是否與當前 key 相同 並且 hash 碼也相同,相同就返回對應的值,不相同就返回 null。

final entrygetentry(object key) 

int hash = (key == null) ? 0 : hash(key);

for (entrye = table[indexfor(hash, table.length)];

e != null;

e = e.next)

return null;

}

HashMap的工作原理和hashtable區別

1.hashmap的工作原理?hashmap底層是陣列 鍊錶 以陣列儲存元素,如有hash相同的元素,在陣列結構中,建立鍊錶結構,再把hash相同的元素放到鍊錶的下乙個節點 基於hashing 雜湊法 雜湊法 是一種將字元組成的字串轉換為固定長度的數值或索引值的方法 的原理。通過put get 方法...

HashMap和LinkedHashMap的區別

hashmap,linkedhashmap,treemap都屬於map map 主要用於儲存鍵 key 值 value 對,根據鍵得到值,因此鍵不允許鍵重複,但允許值重複。hashmap 是乙個最常用的map,它根據鍵的hashcode 值儲存資料,根據鍵可以直接獲取它的值,具有很快的訪問速度。ha...

HashMap和LinkedHashMap的區別

hashmap,linkedhashmap,treemap都屬於map map 主要用於儲存鍵 key 值 value 對,根據鍵得到值,因此鍵不允許鍵重複,但允許值重複。hashmap 是乙個最常用的map,它根據鍵的hashcode 值儲存資料,根據鍵可以直接獲取它的值,具有很快的訪問速度。ha...