Hashtable 從jdk1.0就有了,而HashMap是jdk1.2添加了,ConcurrentHashMap在jdk1.5才提供。Hashtable和ConcurrentHashMap都是線程安全的。但是ConcurrentHashMap是1.5添加的更高級的并發工具。它使用了分段鎖技術來實現更細粒度的同步。因此ConcurrentHashMap比Hashtable效率較高,因此在多線程情況下一般使用ConcurrentHashMap。而HashMap是非線程安全的,因此一般在單線程下使用。
優先選擇:多線程訪問:ConcurrentHashMap。單線程訪問:HashMap
驗證寫個簡單易懂的代碼作為例子,代碼如下,然后分別在有注釋的兩行代碼前設置斷點:
public class HashMapL {public static void main(String[] args) {HashMap<Integer, Integer> hashMap = new HashMap<>();hashMap.put(null, null); //test null key and null value;for(int i=0; i<16; i++){hashMap.put(i, i); //autoboxing}}以debug模式運行上面代碼可以看出HashMap
從上圖可以看到,負載因子loadfactor默認值是0.75。注意,threshold現在的值時0。根據HashMap源碼里面的注釋可以知道,這個值是在給table分配空間后才會計算threshold的值,分配前它的值是0,而現在table的值為null,尚未分配。那么這里的table是什么呢?了解拉鏈式哈希表的人就會輕易知道它是一個鏈表數組。
按F6執行下一步,給hashMap賦值,并且是空值,來驗證與Hashtable的區別:可以保存空值。
從上圖可以看到,
繼續按F6,直到size=threshold=12,此刻table的id和之前的一樣,還是id=24
現在再按一次F6執行下一步,向hashMap里添加一個元素,讓元素的總數size大于閾值threshold
從圖片中看到,table的id=104,大小為32,閾值threshold=24。而之前的id=24,大小為16,threshold=12。因此得出結論,
當元素大小size大于閾值threshold時就會進行再哈希。再哈希后,HashMap就會自動擴容為之前的2倍。并且用一個新的對象代替原來的對象。由此也可得知,自動擴容是需要消耗資源的,要盡量減少自動擴容的發生。參考:API文檔How HashMap works in java,強烈推薦!(之前看了這篇文章感覺真的太好了,有種自己不用寫了感覺。所以這篇博文最主要的目的是總結下HashMap的特點。和這篇文章的debug思路)
新聞熱點
疑難解答