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...