面試專題 HashMap如何在Java中工作

通過優銳課的java學習分享中,瞭解了企業的面試題型,分享給大家學習。

HashMap問題在工作面試中很常見。 這是HashMaps在Java內部如何工作的一些深入說明。

HashMap在內部如何工作已成爲幾乎所有訪談中的一個普遍問題。 幾乎每個人都知道如何使用HashMap或HashMap與Hashtable之間的區別。 但是,當問題爲“ HashMap如何在內部工作?”時,許多人會失敗。

這個問題的答案是,它基於哈希原理工作,但聽起來並不那麼簡單。 哈希是一種使用算法將唯一代碼分配給變量或屬性的機制,從而可以輕鬆進行檢索。 真正的哈希機制在應用於同一對象時應始終返回相同的hashCode()。

然後是一個問題:“哈希如何幫助存儲和檢索HashMap中的值?” 許多人會說該值將存儲在存儲桶中,並使用鍵進行檢索。 如果你認爲這是有效的,那麼你絕對是錯誤的。 爲了證明這一點,讓我們看一下HashMap類:

/**
     * The table, resized as necessary. Length MUST Always be a power of two.
     */
     transient Entry[] table;

那麼HashMap中Entry []的用途是什麼? HashMap將對象存儲爲Entry實例,而不是鍵和值。

什麼是入門班?

HashMap有一個稱爲Entry Class的內部類,其中包含鍵和值。 還有一個叫做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()。爲了在數組範圍內獲得值,調用了hash(key.hashCode()),它對哈希碼執行一些移位操作。
indexFor()方法用於獲取存儲Entry對象的確切位置。

接下來是最重要的部分-如果兩個不同的對象具有相同的哈希碼(例如Aa和BB將具有相同的哈希碼),它將存儲在同一存儲桶中嗎?爲了解決這個問題,讓我們考慮一下數據結構中的LinkedList。它將具有“下一個”屬性,該屬性將始終指向下一個對象,與Entry類中的下一個屬性指向下一個對象的方式相同。使用這種方法,具有相同哈希碼的不同對象將彼此相鄰放置。

對於Collision,HashMap檢查下一個屬性的值。如果爲null,則將Entry對象插入該位置。如果下一個屬性不爲null,則它將保持循環運行,直到下一個屬性爲null,然後將Entry對象存儲在那裏。

如何在HashMap中防止重複密鑰?

衆所周知,HashMap不允許重複鍵,即使當我們插入具有不同值的相同鍵時,也僅返回最新值。

import java.util.HashMap;
import java.util.Map;
public class HashMapEg {
 public static void main(String[] args) {
  Map map = new HashMap();
  map.put(1, "sam");
  map.put(1, "Ian");
  map.put(1, "Scott");
  map.put(null, "asdf");
  System.out.println(map);
 }
}

對於上面的代碼,你將獲得輸出{null = asdf,1 = Scott},因爲值sam和Ian將被替換爲Scott。 那麼,這是怎麼發生的呢?

LinkedList中的所有Entry對象將具有相同的哈希碼,但是HashMap使用equals()。 此方法檢查相等性,因此如果key.equals(k)爲true,它將替換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;
 }

如果兩個鍵具有相同的Hashcode會發生什麼?

此處將使用相同的衝突解決機制。 key.equals(k)將一直檢查到它爲true,如果爲true,則返回它的值。

我希望本文能闡明麻煩的HashMap內部機制。 學習愉快!

喜歡這篇文章的可以點個贊,歡迎大家留言評論,記得關注我,每天持續更新技術乾貨、職場趣事、海量面試資料等等
 > 如果你對java技術很感興趣也可以交流學習,共同學習進步。 
不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代

文章寫道這裏,歡迎完善交流。最後奉上近期整理出來的一套完整的java架構思維導圖,分享給大家對照知識點參考學習。有更多JVM、Mysql、Tomcat、Spring Boot、Spring Cloud、Zookeeper、Kafka、RabbitMQ、RockerMQ、Redis、ELK、Git等Java乾貨

面試專題 HashMap如何在Java中工作

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章