在Java中,當使用?new HashMap<>(10)
?初始化一個容量為10的?HashMap
?但尚未添加任何數據時,其實際容量(底層數組的長度)不是10,而是16。原因如下:
關鍵機制解析:
容量必須是2的冪
HashMap要求容量始終為2的整數次冪(如16、32等)。這是為了優化哈希計算(index = (n - 1) & hash
)和擴容效率。容量計算規則
當傳入初始容量?initialCapacity
?時,HashMap會通過?tableSizeFor()
?方法計算大于等于該值的最小2的冪。
例如:initialCapacity = 10
?→ 實際容量 =?16initialCapacity = 17
?→ 實際容量 =?32
懶加載機制
在創建HashMap對象時,底層數組并未立即分配內存。實際數組的初始化發生在第一次添加元素(put()
操作)時。此時才會根據上述規則創建長度為16的數組。
驗證代碼示例:
import java.lang.reflect.Field;
import java.util.HashMap;public class HashMapCapacity {public static void main(String[] args) throws Exception {HashMap<Integer, String> map = new HashMap<>(10);// 反射獲取底層數組字段Field tableField = HashMap.class.getDeclaredField("table");tableField.setAccessible(true);// 未添加數據時數組為nullObject[] table = (Object[]) tableField.get(map);System.out.println("初始未添加數據時數組: " + table); // 輸出: null// 添加一個元素觸發初始化map.put(1, "A");table = (Object[]) tableField.get(map);System.out.println("添加數據后數組長度: " + table.length); // 輸出: 16}
}
輸出結果:
初始未添加數據時數組: null
添加數據后數組長度: 16
總結:
階段 | 實際容量 | 說明 |
---|---|---|
初始化后(未添加數據) | 0 | 底層數組尚未創建(table = null ) |
首次添加數據后 | 16 | 底層數組初始化為大于10的最小2次冪 |
因此,雖然指定了初始容量為10,但HashMap的實際容量在首次添加數據時會被調整為16。這一設計既滿足了容量必須為2的冪的要求,又通過懶加載優化了內存使用。