面试官提问:
你知道
ArrayList
和HashMap
的默认初始大小是多少吗?为什么是这个值?
标准回答:
-
ArrayList
的默认初始大小是 10。 -
HashMap
的默认初始大小是 16,负载因子为 0.75。
1. ArrayList
默认大小及扩容机制
ArrayList
默认初始容量是 10,这一默认值在 JDK 1.8 之前是创建时分配的,而在 JDK 1.8 及以后,ArrayList
在第一次 add()
操作时才会初始化容量。
扩容机制:
当 ArrayList
需要扩容时,容量会增加到 原来的 1.5 倍(即 oldCapacity + (oldCapacity >> 1)
)。
示例代码:
import java.util.ArrayList;
import java.lang.reflect.Field;
public class ArrayListSizeTest {
public static void main(String[] args) throws Exception {
ArrayList<Integer> list = new ArrayList<>();
list.add(1); // 触发初始化
// 反射查看 ArrayList 的容量
Field field = ArrayList.class.getDeclaredField("elementData");
field.setAccessible(true);
Object[] array = (Object[]) field.get(list);
System.out.println("ArrayList 默认初始大小: " + array.length); // 输出 10
}
}
面试官可能的深入问题:
-
为什么
ArrayList
选择 10 作为默认大小?-
主要是一个经验值,平衡了空间和性能,避免小数据量时的频繁扩容。
-
-
ArrayList
扩容后,会发生什么?-
旧数据会被拷贝到新的数组中,这个过程开销较大,所以建议在创建
ArrayList
时,预估所需容量,使用new ArrayList<>(size)
指定初始大小。
-
2. HashMap
默认大小及扩容机制
HashMap
的默认初始大小是 16,默认负载因子是 0.75。
扩容机制:
-
HashMap
的容量始终是 2 的幂,这样可以更高效地利用 按位与运算 (&
) 来计算索引。 -
当键值对数量超过
capacity * loadFactor
时,HashMap
触发扩容。 -
扩容规则:容量翻倍(变为
oldCapacity * 2
),并重新计算每个元素的位置。
示例代码:
import java.util.HashMap;
import java.lang.reflect.Field;
public class HashMapSizeTest {
public static void main(String[] args) throws Exception {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one"); // 触发初始化
// 反射获取 HashMap 的容量
Field tableField = HashMap.class.getDeclaredField("table");
tableField.setAccessible(true);
Object[] table = (Object[]) tableField.get(map);
System.out.println("HashMap 默认初始大小: " + table.length); // 输出 16
}
}
面试官可能的深入问题:
-
为什么
HashMap
默认初始大小是 16?-
选择 2 的幂次方(如 16、32、64)可以优化 取模运算,提高存取效率。
-
-
为什么
HashMap
采用 0.75 作为默认负载因子?-
0.75 是时间和空间效率的一个折中值,既减少了碰撞,又避免了频繁扩容。
-
-
HashMap
何时扩容?-
当存储的元素个数超过
capacity * loadFactor
时,HashMap
触发扩容(默认16 * 0.75 = 12
)。
-
3. ArrayList
和 HashMap
的扩容对比
数据结构 | 默认大小 | 负载因子 | 触发扩容的条件 | 扩容方式 |
---|---|---|---|---|
ArrayList | 10 | N/A | 元素个数超过当前容量 | 1.5 倍增长 |
HashMap | 16 | 0.75 | 存储元素个数超过 capacity * loadFactor | 容量翻倍 |
总结:
-
ArrayList
适用于 有序存储、频繁随机访问 的场景,建议指定初始容量减少扩容成本。 -
HashMap
适用于 键值对存储,默认容量为 16,负载因子 0.75,扩容时翻倍,保证查找效率。 -
扩容操作会有 性能开销,应尽量 提前估算并设置合适的初始大小,避免不必要的扩容。
如果面试官深入追问,你可以结合实际应用场景说明如何优化这两种数据结构的性能!
如果觉得这篇博客对你有帮助,记得点赞 ⭐、收藏 📌、关注 🚀!