date: 2017-03-26 19:55:33
先上兩張圖攻锰,比較清晰地解釋了java中常用集合之間的關(guān)系失驶。
HashMap與Hashtable的區(qū)別
1.HashMap不是同步的膳沽,線程不安全窒盐。hashtable則是同步的亏镰,線程安全腊满,但不建議在新代碼中使用套么,在不需要線程安全的情況下培己,可以用HashMap代替,在需要線程安全的情況胚泌,可以使用ConcurrentHashMap替代省咨。
2.HashMap允許鍵值為空,HashTable不允許诸迟。
3.方法上茸炒,HashMap去掉了Hashtable的contains方法。
4.Hashtable是基于陳舊的Dictionary的Map接口的實現(xiàn)阵苇,而HashMap是基于哈希表的Map接口的實現(xiàn)
5.HashMap的iterator迭代器執(zhí)行快速失敗機制壁公,也就是說在迭代過程中修改集合結(jié)構(gòu),除非調(diào)用迭代器自身的remove方法绅项,否則以其他任何方式的修改都將拋出并發(fā)修改異常紊册。而Hashtable返回的Enumeration不是快速失敗的。
認識HashMap
HashMap的存儲結(jié)構(gòu)
HashMap是用數(shù)組+鏈表+紅黑樹(jdk1.8)來實現(xiàn)的快耿。
哈希表為解決沖突囊陡,可以采用開放地址法和鏈地址法等來解決問題,Java中HashMap采用了鏈地址法掀亥。hash表的每個元素又分別鏈接著一個單鏈表撞反,元素為頭結(jié)點,如果不同的key映射到了相同的下標搪花,那么就使用頭插法遏片,插入到該元素對應的鏈表。
HashMap的負載因子
首先撮竿,HashMap的初始化長度length(默認值是16)吮便,Load factor為負載因子(默認值是0.75)。
負載因子=哈希表中的元素/哈希表的長度
默認的負載因子0.75是對空間和時間效率的一個平衡選擇
哈希表長度固定的情況下
當負載因子增大幢踏,空間的利用率增大髓需,Hash沖突的概率增加,在進行g(shù)et房蝉,put操作時,消耗更多時間,節(jié)約內(nèi)存;
當負載因子減小僚匆,空間的利用率減小,Hash沖突的概率降低搭幻,讀取性能更好,但會占用更多內(nèi)存;
能否讓HashMap實現(xiàn)線程安全白热,如何做?
1粗卜、直接使用Hashtable屋确,但是當一個線程訪問HashTable的同步方法時,其他線程如果也要訪問同步方法,會被阻塞住攻臀。舉個例子焕数,當一個線程使用put方法時,另一個線程不但不可以使用put方法刨啸,連get方法都不可以堡赔,效率很低,現(xiàn)在基本不會選擇它了设联。
2善已、HashMap可以通過下面的語句進行同步:
Collections.synchronizeMap(hashMap);
3、直接使用JDK 5 之后的 ConcurrentHashMap离例,如果使用Java 5或以上的話换团,請使用ConcurrentHashMap。
JDK1.8中的HashMap
當HashMap因Hash沖突導致鏈表過長時,HashMap會動態(tài)的將它替換成一個紅黑樹宫蛆,這話的話會將時間復雜度從O(n)降為O(logn),很大程度上提高了HashMap的性能艘包。
認識HashTable
Hashtable繼承于Dictionary類,實現(xiàn)了Map接口耀盗。Dictionary是聲明了操作"鍵值對"函數(shù)接口的抽象類想虎。 有一點注意,HashTable除了線程安全之外(其實是直接在方法上增加了synchronized關(guān)鍵字叛拷,比較古老舌厨,落后,低效的同步方式)忿薇,還有就是它的key裙椭、value都不為null。另外Hashtable 也有 初始容量 和 加載因子煌恢。
默認加載因子也是 0.75骇陈,HashTable在不指定容量的情況下的默認容量為11震庭。
參考文章:
美團:Java 8系列之重新認識HashMap
極樂科技Java集合專題總結(jié)(1):HashMap 和 HashTable 源碼學習和面試總結(jié)
官方hashtable API
官方HashMap api