HashMap和Hashtable的區別

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

HashMap和Hashtable的區別

1.二者最主要的區別在於Hashtable是線程安全,而HashMap則非線程安全
Hashtable的實現方法裏面都添加了synchronized關鍵字來確保線程同步,所以相對而言HashMap性能會高一些,咱們平時使用時若無特殊需求建議使用HashMap,在多線程環境下若使用HashMap須要使用Collections.synchronizedMap()方法來獲取一個線程安全的集合(Collections.synchronizedMap()實現原理是Collections定義了一個SynchronizedMap的內部類,這個類實現了Map接口,在調用方法時使用synchronized來保證線程同步,固然了實際上操做的仍是咱們傳入的HashMap實例,簡單的說就是Collections.synchronizedMap()方法幫咱們在操做HashMap時自動添加了synchronized來實現線程同步,相似的其它Collections.synchronizedXX方法也是相似原理)數組

2.HashMap可使用null做爲key,而Hashtable則不容許null做爲key
雖然說HashMap支持null值做爲key,不過建議仍是儘可能避免這樣使用,由於一旦不當心使用了,若所以引起一些問題,排查起來非常費事
HashMap以null做爲key時,老是存儲在table數組的第一個節點上安全

3.HashMap是對Map接口的實現,HashTable實現了Map接口和Dictionary抽象類多線程

4.HashMap的初始容量爲16,Hashtable初始容量爲11,二者的填充因子默認都是0.75
HashMap擴容時是當前容量翻倍即:capacity*2,Hashtable擴容時是容量翻倍+1即:capacity*2+1ide

5.二者計算hash的方法不一樣
Hashtable計算hash是直接使用key的hashcode對table數組的長度直接進行取模性能

int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;線程

HashMap計算hash對key的hashcode進行了二次hash,以得到更好的散列值,而後對table數組長度取摸3d

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

6.HashMap和Hashtable的底層實現都是數組+鏈表結構實現code

HashSet和HashMap、Hashtable的區別

除開HashMap和Hashtable外,還有一個hash集合HashSet,有所區別的是HashSet不是key value結構,僅僅是存儲不重複的元素,至關於簡化版的HashMap,只是包含HashMap中的key而已blog

經過查看源碼也證明了這一點,HashSet內部就是使用HashMap實現,只不過HashSet裏面的Ha11shMap全部的value都是同一個Object而已,所以HashSet也是非線程安全的,至於HashSet和Hashtable的區別,HashSet就是個簡化的HashMap的,因此你懂的
下面是HashSet幾個主要方法的實現接口

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

HashMap和Hashtable的實現原理

HashMap和Hashtable的底層實現都是數組+鏈表結構實現的,這點上徹底一致

添加、刪除、獲取元素時都是先計算hash,根據hash和table.length計算index也就是table數組的下標,而後進行相應操做,下面以HashMap爲例說明下它的簡單實現

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

HashMap的建立
HashMap默認初始化時會建立一個默認容量爲16的Entry數組,默認加載因子爲0.75,同時設置臨界值爲16*0.75

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

put方法
HashMap會對null值key進行特殊處理,老是放到table[0]位置
put過程是先計算hash而後經過hash與table.length取摸計算index值,而後將key放到table[index]位置,當table[index]已存在其它元素時,會在table[index]位置造成一個鏈表,將新添加的元素放在table[index],原來的元素經過Entry的next進行連接,這樣以鏈表形式解決hash衝突問題,當元素數量達到臨界值(capactiy*factor)時,則進行擴容,是table數組長度變爲table.length*2

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

get方法
一樣當key爲null時會進行特殊處理,在table[0]的鏈表上查找key爲null的元素
get的過程是先計算hash而後經過hash與table.length取摸計算index值,而後遍歷table[index]上的鏈表,直到找到key,而後返回

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

remove方法
remove方法和put get相似,計算hash,計算index,而後遍歷查找,將找到的元素從table[index]鏈表移除

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

resize方法
resize方法在hashmap中並無公開,這個方法實現了很是重要的hashmap擴容,具體過程爲:先建立一個容量爲table.length*2的新table,修改臨界值,而後把table裏面元素計算hash值並使用hash與table.length*2從新計算index放入到新的table裏面
這裏須要注意下是用每一個元素的hash所有從新計算index,而不是簡單的把原table對應index位置元素簡單的移動到新table對應位置

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

clear()方法
clear方法很是簡單,就是遍歷table而後把每一個位置置爲null,同時修改元素個數爲0
須要注意的是clear方法只會清楚裏面的元素,並不會重置capactiy

containsKey和containsValue
containsKey方法是先計算hash而後使用hash和table.length取摸獲得index值,遍歷table[index]元素查找是否包含key相同的值

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

containsValue方法就比較粗暴了,就是直接遍歷全部元素直到找到value,因而可知HashMap的containsValue方法本質上和普通數組和list的contains方法沒什麼區別,你別期望它會像containsKey那麼高效

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

hash和indexFor

indexFor中的h & (length-1)就至關於h%length,用於計算index也就是在table數組中的下標
hash方法是對hashcode進行二次散列,以得到更好的散列值
爲了更好理解這裏咱們能夠把這兩個方法簡化爲 int index= key.hashCode()/table.length,以put中的方法爲例能夠這樣替換

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

相關文章
相關標籤/搜索