簡體   English   中英

Java Hashmap內部

[英]Java Hashmap Internal

我對Java HashMap類幾乎沒有疑問。 這是我的理解

 transient Entry[] table;

表數組將根據hashCode()的值保存數據。 我需要知道這個數組何時初始化。 數組長度是基於我們在HashMap初始化期間定義的容量還是默認容量16(如果在調用構造函數時未定義)?

hashcode如何縮放到數組索引? 例如,如果哈希碼具有巨大的值,它如何縮放到數組索引,如10,20?

我已經讀過,當達到閾值時,將發生重新散列。 例如,在默認情況下,當16是容量而0.75是負載因子時,則閾值是16*0.75=12 一旦添加了12個項目,將發生重新加載並且容量將增加。 這是否意味着table數組大小增加了?

由於你的帖子有很多問題,我將列舉你的問題作為我答案的一部分。 此外,請注意我將從HashMap的Java 1.8 b132源代碼中獲取答案。

  1. 問:我需要知道這個數組何時被初始化。
    答:只有在數據首次輸入到地圖中時才會初始化table數組(例如put()方法調用)。 它不會作為地圖實例化的一部分本身發生,除非調用復制構造函數,或者將地圖反序列化為對象。
  2. 問:數組長度是基於我們在HashMap初始化期間定義的容量還是默認容量16(如果在調用構造函數時未定義)?
    答:正確, table數組的長度是基於傳遞給構造函數的初始容量。 如果未指定初始容量且調用默認構造函數,則使用默認容量。
  3. 問:哈希碼如何縮放到數組索引?
    答:對於執行此操作的實際代碼本身,請參閱putVal()方法的實現 基本上發生的是代碼采用非常大的哈希值並對表的最后一個元素索引執行bitwise-AND 這有效地使鍵/值對的位置與table數組隨機化。 例如,如果散列值為333(基數為2的101001101)且table數組大小為32(100000),則最后一個元素索引為31(11111)。 因此,所選擇的指數將是11111 & 101001101 == 01101 == 13
  4. 問:我已經讀過,當達到閾值時,將發生重新散列。 ...這是否意味着表數組大小增加了?
    答:或多或少,是的。 超過threshold ,將調整表的大小。 請注意,通過調整大小,不會修改現有的table數組。 而是創建一個新table數組,其容量是第一個table數組的兩倍。 有關詳細信息,請參閱resize()方法的實現
public HashMap(int initialCapacity, float loadFactor) {
     if (initialCapacity < 0)
         throw new IllegalArgumentException("Illegal initial capacity: " +
                                            initialCapacity);
     if (initialCapacity > MAXIMUM_CAPACITY)
         initialCapacity = MAXIMUM_CAPACITY;

     if (loadFactor <= 0 || Float.isNaN(loadFactor))
         throw new IllegalArgumentException("Illegal load factor: " +
                                            loadFactor);

     // Find a power of 2 >= initialCapacity
     int capacity = 1;
     while (capacity < initialCapacity)
         capacity <<= 1;
     this.loadFactor = loadFactor;
     threshold = (int)(capacity * loadFactor);
     table = new Entry[capacity];
     init();
 }

上面的代碼塊解釋了填充table方式和時間。

一旦重新發生,它就不會增加表數組的大小,因為你可以永久地聲明一次數組大小; 它每次都會使用更新的大小創建一個新數組:

void resize(int newCapacity) {
     Entry[] oldTable = table;
     int oldCapacity = oldTable.length;
     if (oldCapacity == MAXIMUM_CAPACITY) {
         threshold = Integer.MAX_VALUE;
         return;
     }
     Entry[] newTable = new Entry[newCapacity];
     transfer(newTable);
     table = newTable;
     threshold = (int)(newCapacity * loadFactor);
 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM