1. 程式人生 > 實用技巧 >java-hashmap 工作原理

java-hashmap 工作原理

HashMap有一個名為Entry類的內部類,其中包含鍵和值。還有一個叫做next的東西,你稍後就會知道。

 static class Entry<K,V> implements Map.Entry<K,V> 
 {
     final K key;
     V value;
     Entry<K,V> next;
     final int hash;
     ........
 }

你應該知道HashMap將Entry例項儲存在陣列中,而不是作為鍵值對儲存。為了儲存值,都是使用HashMap的put()方法。讓我們深入研究一下,看看它是如何工作的。

Put()方法如何在內部工作?

程式碼如下:

public V put(K key, V value) 
{
    if (key == null)
       return putForNullKey(value);
    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) 
    {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) 
         {
             V oldValue 
= e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }

首先,它檢查給定的金鑰是否為null。如果給定鍵為null,則它將儲存在零位置,因為null的Hashcode將為零。

然後,通過呼叫hashcode方法將hashcode應用於鍵. hashcode()。為了獲得陣列範圍內的值,將呼叫hash(key.hashCode()),它將對hashcode執行一些移位操作。

indexFor()方法用於獲取儲存條目物件的確切位置。

接下來是最重要的部分——如果兩個不同的物件具有相同的hashcode(例如Aa和BB將具有相同的hashcode),那麼它會儲存在同一個bucket中嗎?為了處理這個問題,讓我們考慮資料結構中的LinkedList。它將有一個“next”屬性,它總是指向下一個物件,就像條目類中的下一個屬性指向下一個物件一樣。使用具有相同hashcode的不同物件將彼此放置在一起。

在發生衝突的情況下,HashMap將檢查下一個屬性的值。如果為空,則將條目物件插入該位置。如果下一個屬性不為空,那麼它將保持迴圈執行,直到下一個屬性為空,然後將條目物件儲存在那裡。

如何在HashMap中防止重複鍵?

眾所周知,HashMap不允許重複鍵,即使在插入具有不同值的相同鍵時,也只返回最新的值。

LinkedList中的所有條目物件都有相同的hashcode,但HashMap使用equals()。這個方法檢查相等性,因此如果key.equals(k)為真,它將替換Entry類中的值物件,而不是鍵。通過這種方式,它可以防止插入重複的鍵。

Get()方法如何在內部工作?

將使用put()方法中應用的幾乎相同的邏輯來檢索值。

public V get(Object key) 
{
    if (key == null)
       return getForNullKey();
     int hash = hash(key.hashCode());
     for (Entry<K,V> e = table[indexFor(hash, table.length)];e != null;e = e.next) 
     {
         Object k;
         if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
             return e.value;
     }
         return null;
 }

首先,它獲取傳遞的密匙物件的雜湊碼,並查詢bucket位置。

  • 如果找到了正確的bucket,它將返回該值。
  • 如果沒有找到匹配,則返回null。
  • 如果兩個鍵具有相同的Hashcode會發生什麼?

這裡將使用相同的衝突解決機制。key.equals(k)將檢查,直到它為真,如果為真,它將返回它的值。

轉載自 https://zhuanlan.zhihu.com/p/98883914