在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的幂的要求,又通过懒加载优化了内存使用。