HashMap在put數據時是如何找到要存放的位置的?

初印象:初識HashMap時,知道HashMap是用來存放Key-Value這樣的鍵值對的,也知道HashMap的底層數據結構是:數組+鏈表+紅黑樹,且數組長度爲2的x次冪。
疑問:那麼往HashMap中添加鍵值對時,是什麼決定了鍵值對的存放位置呢?即存放位置是如何計算出來的呢?相同的疑問可能還會以下面的問題描述方式提出來:
其他描述方式:
1.向HashMap中put數據時,數據是如何找到HashMap中Node<K,V>[] table數組的對應索引下標位置的?
2.HashMap在put<K,V>時是如何找到要存放的數組索引下標的位置的?鍵值對是如何與數組索引下標產生映射關聯關係的?
比如有個HashMap的數組中有16個索引下標位置,一個數據過來要put到HashMap中,是誰來決定該元素會被分配到具體哪個索引下標位置的?如何保證哪塊代碼處理的?

分析:既然是由put方法引出的問題,自然要到put的源代碼裏找尋線索。當我們認真研讀put的源碼時會發現下面這三段代碼,我們分別解讀一下:

  1. put調用putVal方法:
    public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
    }
  2. 根據Key-鍵值計算出新的哈希碼值:
    static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
     這段代碼裏首先調用Object的hashCode()方法,計算出key的原始哈希碼;
     然後,將原始哈希碼無符號右移了16位,即高16位被移到了低16位(
    問1:爲啥做無符號右移操作,即爲啥要從高位往低位移動呢?移動後又爲何要做異或操作?
    答1:低位不確保有沒有1,但高位肯定有1,拿無符號右移後的值與原值做異或操作,可以得到一個1的分佈在高低位相對更加均勻的結果。(爲啥要得到這樣的結果呢?是爲了在跟數組長度一起做&與運算計算索引下標時,得到相對更加均勻分撒的結果,這樣根據不同key得出的數組索引下標儘可能分撒的話,就不容易發生哈希碰撞,也就降低了一開始往HashMap中添加數據時鏈表的產生機率)
    問2:爲啥又非得是16位呢?
    答2:因爲hashCode是一個int整形32位,高16位無符號右移16位,可以保證高位與低位能充分混合,這樣的話,再拿無符號右移後的值與原值做異或操作,可以使得1在高低位的分佈更加均勻。
    )
     然後無符號右移後的值與原哈希碼值做異或操作,得到一個1的分佈在高低位相對更加均勻的新哈希碼值。
  3. 根據數組長度及新哈希碼計算索引位置:
    在put調用的putVal方法的裏,有這麼一段代碼:
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
    n = (tab = resize()).length;
    if ((p = tab[i = (n - 1) & hash]) == null)
    ………………………………後續代碼省略…………………………………………
    注意第2個if語句裏隱藏了這麼一句:p = tab[i = (n - 1) & hash]
    這裏就是根據數組長度和新哈希碼值計算數組下標的地方,其中:
     tab從第三段代碼可以看到是從table得來的,而table就是HashMap中的存放鏈表頭節點的數組:Node<K,V> table;
     n是數組的長度,爲2的x次冪的數,故(n-1)代表的二進制位全是1;
     hash是從第二段代碼中得到的新哈希值
     由上可以進而推導出,在公式(n-1)&hash中:
    當hash全爲0時,得到最小值爲0;
    當hash全爲1時,得到最大值爲(n-1);
    當hash部分爲0部分爲1時,得到介於最大值和最小值之間的整數;
    這樣就確保了,根據就根據key得到了要存放的數組索引下標,而且該下標肯定會落在數組長度對應的索引範圍內。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章