← 每日面试题 学习看板

ArrayList、LinkedList与Vector的区别?

面试题/00java/01Java 基础/05 集合/ArrayList、LinkedList与Vector的区别?.md

完整讲解(权威版)

最后更新:2026-11-01 · 基于第 1 次作答

L1 · 30 秒速记

结论:三者都是 List 接口实现,本质差异在底层结构——ArrayList/Vector 基于动态数组、LinkedList 基于双向链表,由此决定读写增删性能与线程安全边界。 关键词:动态数组扩容 1.5x · 双向链表指针 · synchronized 边界:链表 O(1) 增删的前提是已持有节点引用,否则定位仍 O(n);线程安全读多写少优先 CopyOnWriteArrayList。

L2 · 核心讲解

核心考点定位:考察 Java 集合框架三种 List 实现的底层结构差异,以及从底层结构推导出的读写增删性能与线程安全边界;面试官想看到"从底层实现推能力",而不是背结论。

机制链(≥3 环):

  1. ArrayList 基于动态数组 → 元素存于连续内存 Object[] elementData → 按下标 O(1) 随机访问;但中间插入/删除需搬运后续元素 → O(n)。
  2. 数组容量固定 → 元素数达到容量需扩容 grow()(默认 1.5 倍)→ 新建数组 + System.arraycopy 整体迁移 → 扩容成本随规模上升。
  3. LinkedList 基于双向链表 → 每个节点含 prev/next 指针 → 增删只改指针 O(1);但定位任意节点仍需从首/尾遍历 → O(n)。
  4. Vector 用 synchronized 修饰方法 → 线程安全,但整方法加锁 → 并发读写串行化、吞吐低 → JDK 已标记过时,读多写少用 CopyOnWriteArrayList 替代。

证据锚点:

对比与权衡:

维度ArrayListLinkedListVector
底层结构动态数组双向链表动态数组
随机访问O(1)O(n) 遍历O(1)
中间增删O(n) 搬运O(n) 定位 + O(1) 指针O(n) 搬运
头尾增删尾部均摊 O(1)O(1)尾部均摊 O(1)
线程安全否否方法级 synchronized
扩容1.5 倍无2 倍

常见误区:

  1. 错误:"LinkedList 增删一定比 ArrayList 快" → 正确:只有"已定位到节点"时 O(1),任意位置增删仍需 O(n) 遍历定位 → 为什么:链表的 O(1) 增删前提是持有节点引用,否则先要遍历到目标。
  2. 错误:"Vector 已废弃就绝不使用" → 正确:过时但未删除,线程安全读多写少时优先 CopyOnWriteArrayList → 为什么:Vector 的整方法 synchronized 全局锁,写并发吞吐低。
  3. 错误:"ArrayList 扩容是 2 倍" → 正确:ArrayList 默认 1.5 倍(Vector 才是 2 倍)→ 为什么:1.5 倍在"扩容频率"与"内存浪费/拷贝成本"间折中。
  4. 错误:"ArrayList 和 Vector 性能一样" → 正确:Vector 每次增删都加锁,且有同步开销,单线程下比 ArrayList 慢 → 为什么:锁竞争与内存屏障开销。

适用边界:

延伸追问(≥3)

  1. ArrayList 为什么扩容 1.5 倍而不是 2 倍?
  1. LinkedList 头尾增删如何做到 O(1)?
  1. fail-fast 是什么?
  1. CopyOnWriteArrayList 有什么代价?

面试者参考回答

【结论】 三者都是 List 接口实现,本质差异在底层结构:ArrayList/Vector 基于动态数组、LinkedList 基于双向链表,由此决定读写增删性能与线程安全。

【三点】

第一,随机访问:ArrayList/Vector 按下标 O(1),LinkedList 需 O(n) 遍历;所以"按位置查"用数组实现。

第二,增删:链表只改指针,数组要搬运后续元素;但链表增删前要先 O(n) 定位,所以"头尾频繁增删"才占优。

第三,线程安全与扩容:Vector 方法 synchronized、扩容 2 倍,已过时;ArrayList 扩容 1.5 倍且非线程安全;读多写少需要线程安全时用 CopyOnWriteArrayList。

【边界】 链表 O(1) 增删的前提是已持有节点引用,否则定位仍 O(n);线程安全按"读多写少"选 CopyOnWriteArrayList,写多时其整数组复制成本高,反而不划算。

面试记录 2026-11-01(第 1 次)

题目:ArrayList、LinkedList 与 Vector 的区别?

难度:low

标签:java/collections, java/collections, general/knowledge, difficulty/low

评分:⭐⭐⭐⭐☆(4/5)

我的回答

三者都是list集合,但是三者各有取舍,其中arraylist和linkedlist都是非线程安全的,而vector是线程安全的;

但是vector已经作废不推荐使用了,线程安全有对应需求的时候可以使用copyonwriteArraylist

arraylist和linkedlist的核心区别是底层实现,以及不同底层实现带来的不同能力;

arraylist是基于数组实现的,可以快速定位到指定位置,快速替换,快速读取,但是增加删除节点的时候成本较高,需要移动其他节点,并且扩容需要进行整体迁移

LinkedList是基于链表实现,可以快速增减头结点和尾节点,但是查找某个中间位置的时候需要遍历读取,但是在增加节点和删除节点的时候可以很快执行遍历到位置移动指针就可以实现

点评

评分:⭐⭐⭐⭐☆(4/5)

优点:准确说出三者都是 List;Array/List 线程安全差异、Vector 已废弃建议 CopyOnWriteArrayList;底层实现(数组 vs 链表)与随之而来的读写增删差异讲得很清楚。

不足:漏了 Vector 的方法级 synchronized + 默认容量 10、扩容 2 倍;ArrayList 扩容 1.5 倍;LinkedList 是双向链表(含头尾哨兵);CopyOnWriteArrayList 适用场景(读多写少)未展开。

补充:补①Vector 的 synchronized + 2 倍扩容;②ArrayList 1.5 倍扩容与 System.arraycopy 迁移;③链表"增删快"的前提是已定位到节点。

完整讲解见上方「完整讲解(权威版)」