區(qū)別:
(1)HashTable繼承過時的Dictionary抽象類,并實現(xiàn)Map接口;HashMap繼承自AbstractMap抽象類,而AbstractMap抽象類實現(xiàn)了Map接口
(2)HashTable類的方法是同步的,即線程安全的;HashMap類的方法不是同步的,即線程不安全的
(3)HashTable類對于存儲的鍵值,不允許有null;HashMap類對于存儲的鍵值允許有null
(4)HashTable默認(rèn)初始容量是11,擴容是以2倍+1擴容;HashMap默認(rèn)初始容量是4,擴容是以2倍擴容
HashMap實現(xiàn)原理:
(1)HashMap內(nèi)部是基于數(shù)組+單向鏈表的結(jié)構(gòu)實現(xiàn)的。
(2)當(dāng)new一個HashMap的時候,參照HashMap的構(gòu)造方法,如果不指定初始容量和加載因子的話,默認(rèn)的初始容量是16,加載因子是0.75f,如果設(shè)置的初始容量小于2的2次方,或者大于2的30次方,則按照2的2次方和2的30次方來算
(3)在第一次put數(shù)據(jù)到HashMap中的時候,會去inflateTable,就是new一個初始容量長度的HashMapEntry[]數(shù)組,并指定擴容臨界值(初始容量*加載因子,并一定是2的冪次方)
(4)如果put的數(shù)據(jù),key為null的話,則總會放在HashMapEntry[]的0索引位置鏈表里
(5)put數(shù)據(jù)的過程(key為null即是數(shù)組中0位置):通過key計算hash值,然后hash值對數(shù)組的length取模獲得該數(shù)據(jù)應(yīng)在數(shù)組的index,若index位置沒有元素,則new一個HashMapEntry放到該位置,并返回null;若index位置有元素,則遍歷index位置的單向鏈表,如果找到key相同的元素了,則用新值替換舊值,并把舊值返回回去,若沒找到,則new一個HashMapEntry放到index位置,原來單向鏈表的頭部元素通過HashMapEntry的next進行鏈接起來
(6)在put數(shù)據(jù)的過程中,如果當(dāng)前容量達(dá)到擴容臨界值,則會新建一個容量是原來數(shù)組長度2倍的新數(shù)組,并根據(jù)新數(shù)組的length重新計算,舊數(shù)組中的數(shù)據(jù)在新數(shù)組的位置,把舊數(shù)組中的數(shù)據(jù)放到新數(shù)組中,并重新計算擴容臨界值
(7)get數(shù)據(jù)的話,若當(dāng)前size為0,則直接返回null,若key為null,依然遍歷數(shù)組0索引位置的單向鏈表,找到key為null的元素,把值返回回去,如果沒找到或者數(shù)組0索引位置沒有元素則返回null
(8)get數(shù)據(jù)過程:通過key計算hash值,然后hash值對數(shù)組的length取模獲得該數(shù)據(jù)應(yīng)在數(shù)組的index,然后遍歷該位置的單向鏈表,找到與key相同的元素,返回,其他默認(rèn)都返回null
(9)remove數(shù)據(jù)過程:通過key計算hash值,然后hash值對數(shù)組的length取模獲得該數(shù)據(jù)應(yīng)在數(shù)組的index,然后遍歷index位置的單向鏈表,找到hash值相同并且key相同的元素,移除它,并把后一個元素鏈接到前一個元素的next上,其他size為0或者index位置沒數(shù)據(jù)或者index位置的單向鏈表遍歷完了沒找到,則都返回null
(10)clear數(shù)據(jù)過程:遍歷數(shù)組,每個位置元素都置為null