应使用 LinkedList 的 Deque 方法(如 push/pop/offer/poll)实现栈和队列,避免随机访问和 Stack 类;push/pop 等价于 addFirst/removeFirst,offer/poll 等价于 addLast/removeFirst,时间复杂度均为 O(1),而 get(i) 为 O(n),Stack 类因同步和继承 Vector 已过时。

用 LinkedList 实现栈:注意 push/pop 与 addFirst/removeFirst 的等价性
Java 的 LinkedList 实现了 Deque 接口,天然支持栈语义,但直接调用 push() 和 pop() 比手动操作首尾更安全、意图更明确。
-
push(e)等价于addFirst(e),元素加到链表头部;pop()等价于removeFirst(),抛出NoSuchElementException(而非返回null)——这点和Stack类行为一致 - 避免混用
addLast()和pop(),会导致 LIFO 失效;若需兼容旧代码,优先统一用Deque方法,而非继承自List的索引操作 -
peek()不移除元素,对应element()(抛异常)或peekFirst()(返回null),按需选择容错策略
用 LinkedList 实现队列:offer/poll/peek 是标准做法
作为队列使用时,应完全避开 get(int)、set(int, E) 等随机访问方法——它们时间复杂度是 O(n),违背队列的 O(1) 入队/出队预期。
- 入队统一用
offer(e)(等价于addLast(e)),失败时返回false(比如容量受限的阻塞队列场景,但LinkedList本身无容量限制) - 出队用
poll()(等价于removeFirst()),空时返回null;若必须非空才操作,改用remove()(抛NoSuchElementException) -
peek()返回队首但不移除,对应peekFirst();不要用get(0),它在空列表时抛IndexOutOfBoundsException,且语义模糊
为什么不用 Stack 类而选 LinkedList?性能与设计意图差异
Stack 类是遗留类,继承自 Vector,所有操作同步(synchronized),带来无谓开销;而 LinkedList 是非线程安全的,更轻量,且接口设计更符合现代集合规范。
本书是全面讲述PHP与MySQL的经典之作,书中不但全面介绍了两种技术的核心特性,还讲解了如何高效地结合这两种技术构建健壮的数据驱动的应用程序。本书涵盖了两种技术新版本中出现的最新特性,书中大量实际的示例和深入的分析均来自于作者在这方面多年的专业经验,可用于解决开发者在实际中所面临的各种挑战。
-
Stack的push()/pop()底层仍是Vector的addElement()和removeElementAt(),每次操作都锁整个对象 -
LinkedList的Deque方法(如offerLast())只操作头/尾节点指针,无遍历、无扩容、无同步,平均时间复杂度稳定 O(1) - 若需线程安全,应显式包装为
Collections.synchronizedDeque(new LinkedList())或选用ConcurrentLinkedDeque,而非依赖Stack的过时同步机制
常见误用:把 LinkedList 当作 ArrayList 用
最典型的坑是用 get(i) 遍历或随机访问——LinkedList 没有数组索引缓存,每次 get(i) 都要从头或尾开始遍历节点,O(n) 时间成本在大数据量下极易暴露。
立即学习“Java免费学习笔记(深入)”;
- 需要频繁随机访问?换
ArrayList;需要高频首尾增删?才选LinkedList - 用
for (E e : list)迭代是安全的,底层走的是迭代器(双向链表遍历优化过);但for (int i = 0; i 就是灾难 -
size()是 O(1),但indexOf()、lastIndexOf()、contains()全是 O(n),别在大链表里查值
LinkedList 做栈/队列的关键,不是“它能实现”,而是“你是否真的只做头尾操作”。一旦出现中间插入、按索引取值、批量排序等需求,它立刻变成负优化。









