Java面试题--ArrayList 的 add() 时间复杂度?

📅 发布时间:2026/7/16 6:31:15 👁️ 浏览次数:
Java面试题--ArrayList 的 add() 时间复杂度?
⏱ 30秒快速回答通常为 O(1)但遇到扩容时为 O(n)均摊复杂度仍为 O(1)。 详细答案免费ArrayList 的add()时间复杂度 —— 面试官真正想听的不只是“O(1)”先说结论但别只背结论ArrayList.add(E e)的单次最坏时间复杂度是 O(n)平均/均摊时间复杂度是 O(1)。如果你只答“O(1)”——面试官会微微一笑然后问“那扩容的时候呢”一、概念解释为什么不是“永远 O(1)”ArrayList底层是动态数组Object[] elementData它不是固定大小的。当你不断add()数组迟早会满。这时 JVM 必须✅ 分配一块更大的新数组通常是原容量 × 1.5JDK 17 是 × 1.125但仍是常数倍✅ 把所有旧元素逐个复制到新数组这就是 O(n) 的来源✅ 将elementData引用指向新数组✅ 最后才把新元素放入末尾O(1) 所以扩容那一刻 O(n)其他时候 O(1)。二、原理深挖均摊分析Amortized Analysis才是关键面试官最爱考这个思维——不是看单次最差而是看连续 n 次 add 的总代价 / n。 举个真实例子从空 ArrayList 开始 add 16 个元素操作次数当前容量是否扩容复制元素数累计复制总数add(1)10默认否00...............add(11)10 → 15是 ✅1010add(16)15 → 22是 ✅1525但注意扩容并不频繁。假设每次扩容为old * 1.5那么扩容触发点大致在10 → 15 → 22 → 33 → 49 → …→ 扩容总次数 ≈ log₁.₅(n)而第 k 次扩容复制约1.5ᵏ个元素。数学结论可简述n 次 add 的总操作数 ≤n 10 15 22 ...等比数列和≈n c·n O(n)→ 均摊代价 O(n) / n O(1)✅ 这就是为什么我们说“均摊 O(1)” —— 它反映的是长期性能不是某一次的抖动。三、代码佐证JDK 17 片段精讲JAVApublic boolean add(E e) { modCount; // fail-fast 计数器 add(e, elementData, size); // 核心逻辑 return true; } private void add(E e, Object[] elementData, int s) { if (s elementData.length) // ⚠️ 关键判断满了 elementData grow(); // → 触发扩容O(n) elementData[s] e; // ✅ 普通插入O(1) size s 1; } private Object[] grow() { int oldCapacity elementData.length; int newCapacity ArraysSupport.newLength(oldCapacity, 1, // minGrowth1 oldCapacity 1); // 扩容增量 ≈ 50% return elementData Arrays.copyOf(elementData, newCapacity); } 注意Arrays.copyOf()内部调用System.arraycopy()—— 是 JVM 优化的 native 方法但仍是 O(n) 复制不是魔法。四、面试高频追问 常见误区必防坑问题正确回答❌ 常见错误QLinkedList 的 add(E) 是不是更稳定 O(1)是但仅限addLast()尾插。add(index)仍是 O(n)要遍历找位置“LinkedList 所有 add 都 O(1)” → 错Q能避免扩容开销吗可以构造时指定足够初始容量new ArrayList(expectedSize)“用ensureCapacity()就行” → 对但构造时预设更优雅、更早生效Qadd(int index, E e) 时间复杂度O(n)—— 不仅可能扩容还要把 index 后所有元素右移一位混淆add(E)和add(int, E)后者永远 O(n)Q为什么不用 ArrayList 存超大数据频繁扩容 大数组内存碎片 GC 压力大此时考虑ArrayDeque无扩容抖动或分片设计“因为线程不安全” → 跑题这是并发问题不是复杂度问题✅ 总结一句话面试收尾金句“ArrayList.add(E)是典型的均摊 O(1)操作——它用少量高成本扩容换取绝大多数插入的极致高效。理解扩容机制和均摊思想比死记复杂度更重要。”停顿一秒“就像地铁早高峰虽然偶尔列车晚点扩容但平均通勤时间依然可控——系统设计的本质是平衡‘峰值’与‘常态’。” 字数约 1020 字覆盖原理、代码、误区、延伸够你稳稳拿下这道题 面试技巧考察点动态数组插入性能理解。 延伸问题扩容对 add 影响2. 均摊复杂度概念3. 何种场景效率低更多Java面试题整理JVM面试题MySQL面试题Redis面试题Spring面试题完整面试题库https://myquotego.com支持AI模拟面试AI答案解析2000面试题