HashMap源碼分析(二):看完完全瞭解HashMap

上文講到HashMap的增長方法,如今繼續 上文連接html

HashMap在上一篇源碼分析的文章中,若是使用put的時候若是元素數量超過threshold就會調用resize進行擴容java

1.擴容機制

想要了解HashMap的擴容機制你要有這兩個問題數組

  • 1.何時才須要擴容
  • 2.HashMap的擴容是什麼

在添加元素的時候若是超過threshold設置的閥值點就會進行擴容,簡單的來講就是一個水壺容量是二升,而後這個時候已經滿了可是你還要繼續加水,咋辦?換個大的。因此HashMap的擴容就和你這個水壺同樣,水已經滿了那我就在換個大的水壺繼續加水。不過在你換水壺的時候是有不少條件的。安全

在我看這個resize的源碼的時候我也是一臉懵逼,最後請教了大佬獲得的回答是由於1.8加入了紅黑樹比較麻煩能夠看一下1.7的,而後我有去網上看了一下別人寫的文章基本上都是基於1.7的resize。因此這裏就看1.7的resize來分析。數據結構

來看JDK1.7中resize的實現。源碼分析

複製操做是調用的transfer方法線程

在1.7中的resize結合一下咱們的小例子能夠這樣理解,去超市買一個大一點的水壺,而後把之前水壺裏面的水給倒進新的水壺裏面。再把咱們當前的水壺的容量替換掉,告訴別人個人容量更大了。(強行比喻哈哈哈哈哈)3d

1.7中的resize就是這麼簡單,那咱們在看一下1.8中的resize(),這樣再看就不會一臉懵逼了code

我在這裏把1.8的resize方法分爲兩部分htm

  • 1.計算新的newCap(新的容量)和newThr(新閥值點)
  • 2.複製新的數組

第一部分

第二部分

對比一下1.7

  • 1.7元素不須要更換位置。1.8元素的位置要麼是在原位置,要麼是在原位置再移動2次冪的位置
  • 不須要像1.7同樣從新計算hash

2.刪除

刪除的話就是首先先找到元素的位置,若是是鏈表就遍歷鏈表找到元素以後刪除。若是是用紅黑樹就遍歷樹而後找到以後作刪除,樹小於6的時候要轉鏈表。

刪除方法:

調用removeNode:

3.查找元素

查找方法,經過元素的Key找到Value。

調用getNode()方法

看完能夠知道邏輯是先經過Key計算出索引的位置,而後先檢查第一個節點看看是不是咱們要的節點,若是不是在去查看是否死紅黑樹和鏈表。

4.遍歷

咱們經過下面幾個例子來演示一下HashMap怎麼遍歷

1.分別遍歷Key和Values

for (String key:map.keySet()){
            System.out.println(key);
        }
        for (Object value : map.values()) {
            System.out.println(value);
        }

2.迭代

Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Object> mapEntry = iterator.next();
            System.out.println(mapEntry.getKey() + "====" + mapEntry.getValue());
        }

3.獲取 key 集合

Set<String> keySet = map.keySet();
        for (String str : keySet) {
            System.out.println(str + "====" + map.get(str));
        }

4.獲取Entry 集合,遍歷Entry 集合

Set<Map.Entry<String, Object>> entrySet = map.entrySet();
        for (Map.Entry<String, Object> entry : entrySet) {
            System.out.println(entry.getKey() + "====" + entry.getValue());
        }

對比來講使用迭代的方式是最好的,也能夠在迭代的時候對集合的元素進行刪除

總結

基於JDK1.8的HashMap是由數組+鏈表+紅黑樹組成,當鏈表長度超過 8 時會自動轉換成紅黑樹,當紅黑樹節點個數小於 6 時,又會轉化成鏈表。相對於早期版本的 JDK HashMap 實現,新增了紅黑樹做爲底層數據結構,在數據量較大且哈希碰撞較多時,可以極大的增長檢索的效率。HashMap並非線程安全的,支持K和V爲null ,k重複會覆蓋,V能夠重複,還有一點HashMap遍歷的數據不是有序的是無序的

相關文章
相關標籤/搜索