第1题:说说ArrayList的底层原理/扩容规则
📚 回答:
-
底层实现 :
ArrayList基于动态数组实现,初始底层数组长度取决于构造方式:- 空参构造:初始长度为0(即
elementData为空数组)。 - 有参构造:直接初始化为指定容量的数组(如
new ArrayList<>(20))。
- 空参构造:初始长度为0(即
-
扩容规则:
1. 使用
add方法时的扩容规则- 空参构造 :
- 首次调用
add方法时,扩容到默认容量10。 - 后续扩容:新容量为上一次容量的1.5倍,计算公式为
新容量 = 原容量 + (原容量 >> 1)。
- 首次调用
- 有参构造 :
- 直接初始化为指定容量(如20)。只有当添加的元素数量超过初始容量时,才会触发扩容。
- 扩容规则与空参构造一致:新容量为上一次容量的1.5倍。
2. 使用
addAll方法时的扩容规则-
如果集合原本为空:
扩容后容量取
Math.max(10, 实际元素个数)。 -
如果集合原本有元素:
扩容后容量取
Math.max(原容量1.5倍, 实际元素个数)。
- 空参构造 :
💡 面试官视角:
- 面试官可能会追问"为什么扩容是1.5倍?"答:1.5倍是一个折中值,既能减少频繁扩容的开销,又不会浪费过多内存空间。
- 面试官可能会问"扩容过程中是如何保证线程安全的?"答:
ArrayList本身不是线程安全的,扩容时可能会出现并发问题,比如多个线程同时扩容导致数据不一致。如果需要线程安全,可以使用Collections.synchronizedList或CopyOnWriteArrayList。