從HashMap的常用方法來解析HashMap的內(nèi)部實(shí)現(xiàn)(2)

上篇文章(http://www.itdecent.cn/p/a122c79ee60c
我們分析了HashMap的構(gòu)造和put方法,這篇文章來看看它的其他方法

putAll
  @Override 
  public void putAll(Map<? extends K, ? extends V> map) {
        ensureCapacity(map.size());
        super.putAll(map);
  }

我們來看看 ensureCapacity(map.size());方法

  private void ensureCapacity(int numMappings) {
        int newCapacity = Collections.roundUpToPowerOfTwo(capacityForInitSize(numMappings));
        HashMapEntry<K, V>[] oldTable = table;
        int oldCapacity = oldTable.length;
        if (newCapacity <= oldCapacity) {
            return;
        }
        if (newCapacity == oldCapacity * 2) {
            doubleCapacity();
            return;
        }

        // We're growing by at least 4x, rehash in the obvious way
        HashMapEntry<K, V>[] newTable = makeTable(newCapacity);
        if (size != 0) {
            int newMask = newCapacity - 1;
            for (int i = 0; i < oldCapacity; i++) {
                for (HashMapEntry<K, V> e = oldTable[i]; e != null;) {
                    HashMapEntry<K, V> oldNext = e.next;
                    int newIndex = e.hash & newMask;
                    HashMapEntry<K, V> newNext = newTable[newIndex];
                    newTable[newIndex] = e;
                    e.next = newNext;
                    e = oldNext;
                }
            }
        }
    }

首先得到一個(gè)新的容量newCapacity,如果等于舊容量的2倍就調(diào)用doubleCapacity()方法,這個(gè)方法在上一篇已經(jīng)解析過了,這邊就不再說了,makeTable方法創(chuàng)建一個(gè)新的數(shù)組,上篇文章也解析過了,下面著重看看這個(gè)循環(huán)

    if (size != 0) {
            int newMask = newCapacity - 1;
            for (int i = 0; i < oldCapacity; i++) {
                for (HashMapEntry<K, V> e = oldTable[i]; e != null;) {
                    HashMapEntry<K, V> oldNext = e.next;
                    int newIndex = e.hash & newMask;
                    HashMapEntry<K, V> newNext = newTable[newIndex];
                    newTable[newIndex] = e;
                    e.next = newNext;
                    e = oldNext;
                }
            }
        }

首先計(jì)算出數(shù)據(jù)在新的數(shù)組當(dāng)中的index下標(biāo),如果next有數(shù)據(jù)又改變了鏈表的順利,總之就是把舊數(shù)組當(dāng)中的數(shù)據(jù)添加到了新的數(shù)組當(dāng)中,然后調(diào)用父類的putAll方法

public void putAll(Map<? extends K, ? extends V> map) {
        for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
            put(entry.getKey(), entry.getValue());
        }
}

首先遍歷map對(duì)象參數(shù),然后調(diào)用HashMap的put方法添加數(shù)據(jù)。

get方法

  public V get(Object key) {
        if (key == null) {
            HashMapEntry<K, V> e = entryForNullKey;
            return e == null ? null : e.value;
        }

        int hash = Collections.secondaryHash(key);
        HashMapEntry<K, V>[] tab = table;
        for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
                e != null; e = e.next) {
            K eKey = e.key;
            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
                return e.value;
            }
        }
        return null;
    }

如果key==null,就返回entryForNullKey對(duì)象,不為null,首先計(jì)算hash值,然后計(jì)算index下標(biāo),得到對(duì)象
如果eKey == key || (e.hash == hash && key.equals(eKey)) 條件成立,就返回value。

remove方法

  @Override 
  public V remove(Object key) {
        if (key == null) {
            return removeNullKey();
        }
        int hash = Collections.secondaryHash(key);
        HashMapEntry<K, V>[] tab = table;
        int index = hash & (tab.length - 1);
        for (HashMapEntry<K, V> e = tab[index], prev = null;
                e != null; prev = e, e = e.next) {
            if (e.hash == hash && key.equals(e.key)) {
                if (prev == null) {
                    tab[index] = e.next;
                } else {
                    prev.next = e.next;
                }
                modCount++;
                size--;
                postRemove(e);
                return e.value;
            }
        }
        return null;
    }

如果key為null,調(diào)用removeNullKey方法

  private V removeNullKey() {
        HashMapEntry<K, V> e = entryForNullKey;
        if (e == null) {
            return null;
        }
        entryForNullKey = null;
        modCount++;
        size--;
        postRemove(e);
        return e.value;
    }

設(shè)置entryForNullKey對(duì)象為null。

key不為空

 int hash = Collections.secondaryHash(key);
 HashMapEntry<K, V>[] tab = table;
 int index = hash & (tab.length - 1);
 for (HashMapEntry<K, V> e = tab[index], prev = null;
           e != null; prev = e, e = e.next) {
        if (e.hash == hash && key.equals(e.key)) {
             if (prev == null) {
                 tab[index] = e.next;
              } else {
                prev.next = e.next;
           }
           modCount++;
           size--;
           postRemove(e);
           return e.value;
        }
   }

首先得到index,然后循環(huán)
如果刪除的數(shù)據(jù)在index位置,就把index位置的對(duì)象的下一個(gè)對(duì)象賦值給數(shù)組的index位置。
如果刪除的數(shù)據(jù)在index位置的鏈表中間就把鏈表中間的這個(gè)數(shù)據(jù)刪除掉,然后把中間數(shù)據(jù)的頭和尾連接在一起。

結(jié)束語

到此HashMap的常用方法都分析完了,通過看源碼對(duì)HashMap有了更深的理解。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容