HashMap、Hashtable、HashSet三種hash集合的區別
阿新 • • 發佈:2019-02-12
HashMap和Hashtable的區別
- 兩者最主要的區別在於Hashtable是執行緒安全,而HashMap則非執行緒安全
Hashtable的實現方法裡面都添加了synchronized關鍵字來確保執行緒同步,因此相對而言HashMap效能會高一些,我們平時使用時若無特殊需求建議使用HashMap,在多執行緒環境下若使用HashMap需要使用Collections.synchronizedMap()方法來獲取一個執行緒安全的集合(Collections.synchronizedMap()實現原理是Collections定義了一個SynchronizedMap的內部類,這個類實現了Map介面,在呼叫方法時使用synchronized來保證執行緒同步,當然了實際上操作的還是我們傳入的HashMap例項,簡單的說就是Collections.synchronizedMap()方法幫我們在操作HashMap時自動添加了synchronized來實現執行緒同步,類似的其它Collections.synchronizedXX方法也是類似原理 - HashMap可以使用null作為key,而Hashtable則不允許null作為key
雖說HashMap支援null值作為key,不過建議還是儘量避免這樣使用,因為一旦不小心使用了,若因此引發一些問題,排查起來很是費事
HashMap以null作為key時,總是儲存在table陣列的第一個節點上 - HashMap是對Map介面的實現,HashTable實現了Map介面和Dictionary抽象類
- HashMap的初始容量為16,Hashtable初始容量為11,兩者的填充因子預設都是0.75
HashMap擴容時是當前容量翻倍即:capacity*2,Hashtable擴容時是容量翻倍+1即:capacity*2+1 - 兩者計算hash的方法不同
Hashtable計算hash是直接使用key的hashcode對table陣列的長度直接進行取模int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length;
HashMap計算hash對key的hashcode進行了二次hash,以獲得更好的雜湊值,然後對table陣列長度取摸
static int hash(int h) { // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded
- HashMap和Hashtable的底層實現都是陣列+連結串列結構實現
HashSet和HashMap、Hashtable的區別
除開HashMap和Hashtable外,還有一個hash集合HashSet,有所區別的是HashSet不是key value結構,僅僅是儲存不重複的元素,相當於簡化版的HashMap,只是包含HashMap中的key而已
通過檢視原始碼也證實了這一點,HashSet內部就是使用HashMap實現,只不過HashSet裡面的HashMap所有的value都是同一個Object而已,因此HashSet也是非執行緒安全的,至於HashSet和Hashtable的區別,HashSet就是個簡化的HashMap的,所以你懂的
下面是HashSet幾個主要方法的實現
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object(); public HashSet() { map = new HashMap<E,Object>(); } public boolean contains(Object o) { return map.containsKey(o); } public boolean add(E e) { return map.put(e, PRESENT)==null; } public boolean add(E e) { return map.put(e, PRESENT)==null; } public boolean remove(Object o) { return map.remove(o)==PRESENT; } public void clear() { map.clear(); }