1.HashMap與HashTable相同點(diǎn)
- 1.二者都是以哈希表(數(shù)組+鏈表)數(shù)據(jù)結(jié)構(gòu)存儲數(shù)據(jù).
- 2.二者都可以進(jìn)行數(shù)組擴(kuò)容
2.HashMap與HashTable區(qū)別
1.是否線程安全
HashMap不是線程安全的工三,HashTable是線程安全的;【HashTable內(nèi)部的方法基本都使用了synchronized關(guān)鍵字修飾】
注意:現(xiàn)在HashTable在我們的開發(fā)中很少很少使用偎漫。如果你要保證線程安全清女,推薦使用ConcurrentHashMap2.效率
因?yàn)榫€程安全的問題赶撰,HashMap要比HashTable的效率高一點(diǎn)。3.對于Null Key和Null Value的支持
HashMap中,null可以作為key红氯,但是這樣的key只能有一個(gè);可以有一個(gè)或者多個(gè)鍵對應(yīng)的value為null;
HashTable中不支持key為null咕痛,如果put使用null痢甘,那么就會(huì)拋出NullPointerException異常;4.初始容量和每次擴(kuò)充容量的大小不同
HashMap創(chuàng)建的時(shí)候如果不指定容量大小茉贡,初始容量大小為16塞栅,之后每次擴(kuò)充,容量變?yōu)樵瓉淼?倍腔丧;
HashTable創(chuàng)建的時(shí)候如果不指定容量大小放椰,初始容量大小為11,之后每次擴(kuò)充愉粤,容量會(huì)變?yōu)?n + 1砾医;
HashMap創(chuàng)建的時(shí)候給定初始容量大小,HashMap 會(huì)將其擴(kuò)充為2的冪次方大幸吕濉(HashMap 中的tableSizeFor()方法保證如蚜,下面給出了源代碼)。也就是說 HashMap 總是使用2的冪作為哈希表的大小,后面會(huì)介紹到為什么是2的冪次方影暴。5.繼承的父類不同
HashMap繼承自AbstractMap類错邦。但二者都實(shí)現(xiàn)了Map接口。
Hashtable繼承自Dictionary類型宙,Dictionary類是一個(gè)已經(jīng)被廢棄的類(見其源碼中的注釋)撬呢。父類都被廢棄,自然而然也沒人用它的子類Hashtable了6.支持的遍歷種類不同:
HashMap只支持Iterator遍歷,而HashTable支持Iterator和Enumeration(枚舉)兩種方式遍歷7.計(jì)算hash值方式不同
為了得到元素的位置妆兑,首先需要根據(jù)元素的 KEY計(jì)算出一個(gè)hash值魂拦,然后再用這個(gè)hash值來計(jì)算得到最終的位置。
①:HashMap有個(gè)hash方法重新計(jì)算了key的hash值,因?yàn)閔ash沖突變高搁嗓,所以通過一種方法重算hash值的方法:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
注意:這里計(jì)算hash值晨另,先調(diào)用hashCode方法計(jì)算出來一個(gè)hash值,再將hash與右移16位后相異或(異或計(jì)算方式:相同為0谱姓,不相同為1借尿,可以理解為不進(jìn)位相加),從而得到新的hash值。
例子:
十進(jìn)制:3254818
注意:int類型 占4byte 32位
處理數(shù)據(jù)
二進(jìn)制:11 0001 1010 1010 0010 0010 (22位路翻,不足32位狈癞,則補(bǔ)0到32位)
0000 0000 0011 0001 1010 1010 0010 0010 (32位)
h>>>16 無符號右移16位
0000 0000 0000 0000 0000 0000 0011 0001
^ 異或操作:相同為0,不相同為1茂契,可以理解為不進(jìn)位相加
數(shù)據(jù)處理完畢蝶桶,開始進(jìn)行異或操作
h = key.hashCode() ^ (h >>> 16)
0000 0000 0011 0001 1010 1010 0010 0010 ( h = key.hashCode())
^ (異或)
0000 0000 0000 0000 0000 0000 0011 0001 (h >>> 16)
結(jié)果為:
0000 0000 0011 0001 1010 1010 0001 0011
3245803 (十進(jìn)制結(jié)果)
②:Hashtable通過計(jì)算key的hashCode()來得到hash值就為最終hash值。
- 8.解決hash沖突方式不同(地址沖突)
JDK1.8 以后的 HashMap 在解決哈希沖突時(shí)有了較大的變化掉冶,當(dāng)鏈表長度大于閾值(默認(rèn)為8)時(shí)真竖,將鏈表轉(zhuǎn)化為紅黑樹,以減少搜索時(shí)間厌小;
而在HashTable中恢共, 都是以鏈表方式存儲