Java 中栈(Stack)和队列(Queue)最常用的方法
·
由于 java.util.Stack 是一个遗留类,在现代 Java 开发中已不推荐使用,因此我们将重点放在推荐使用的 Deque (双端队列) 接口来实现栈和队列的功能。Deque 提供了更丰富、更统一的 API。
核心接口:Deque<E>
Deque (Double-Ended Queue) 是一个双端队列,它允许在队列的两端(头部和尾部)进行元素的插入和删除。通过限制只在一端进行操作,我们就可以很方便地实现栈和队列。
- 实现栈 (Stack):只使用
Deque的尾部 (Tail) 进行插入和删除操作。 - 实现队列 (Queue):只使用
Deque的尾部 (Tail) 进行插入,头部 (Head) 进行删除操作。
最常用的 Deque 实现类是 ArrayDeque 和 LinkedList。
ArrayDeque: 基于动态数组实现,性能更高,是推荐的默认选择。LinkedList: 基于双向链表实现,在某些特定场景(如频繁在中间插入 / 删除)有优势。
一、栈 (Stack) 常用方法
使用 Deque 实现栈时,我们主要关注操作尾部 (Tail) 的方法。
| 方法 | 作用 | 异常处理 | 推荐度 |
|---|---|---|---|
push(e) |
压栈:将元素添加到栈顶(Deque 的尾部)。 |
如果栈已满(对于有界 Deque),抛出 IllegalStateException。 |
极高 (最常用的入栈方法) |
pop() |
弹栈:移除并返回栈顶(Deque 的尾部)的元素。 |
如果栈为空,抛出 NoSuchElementException。 |
极高 (最常用的出栈方法) |
peek() |
查看栈顶:返回栈顶(Deque 的尾部)的元素,但不移除它。 |
如果栈为空,返回 null。 |
极高 (安全地查看栈顶元素) |
代码示例:
import java.util.Deque;
import java.util.ArrayDeque;
public class StackExample {
public static void main(String[] args) {
// 使用 ArrayDeque 作为栈
Deque<Integer> stack = new ArrayDeque<>();
// push() - 入栈
stack.push(10);
stack.push(20);
stack.push(30);
System.out.println("Stack after pushes: " + stack); // [10, 20, 30] (注意: toString()显示顺序是头到尾,栈顶是30)
// peek() - 查看栈顶
System.out.println("Top element (peek): " + stack.peek()); // 30
System.out.println("Stack after peek: " + stack); // [10, 20, 30] (不变)
// pop() - 出栈
System.out.println("Popped element: " + stack.pop()); // 30
System.out.println("Stack after pop: " + stack); // [10, 20]
}
}
二、队列 (Queue) 常用方法
使用 Deque 实现队列时,我们主要关注尾部插入,头部删除。
| 方法 | 作用 | 异常处理 | 推荐度 |
|---|---|---|---|
add(e) |
入队:将元素添加到队列尾部。 | 如果队列已满,抛出 IllegalStateException。 |
高 |
offer(e) |
入队:将元素添加到队列尾部。 | 如果队列已满,返回 false。 |
极高 (更安全,因为它不会抛出异常) |
remove() |
出队:移除并返回队列头部的元素。 | 如果队列为空,抛出 NoSuchElementException。 |
高 |
poll() |
出队:移除并返回队列头部的元素。 | 如果队列为空,返回 null。 |
极高 (更安全,因为它不会抛出异常) |
element() |
查看队头:返回队列头部的元素,但不移除它。 | 如果队列为空,抛出 NoSuchElementException。 |
高 |
peek() |
查看队头:返回队列头部的元素,但不移除它。 | 如果队列为空,返回 null。 |
极高 (更安全,因为它不会抛出异常) |
代码示例:
import java.util.Deque;
import java.util.ArrayDeque;
public class QueueExample {
public static void main(String[] args) {
// 使用 ArrayDeque 作为队列
Deque<String> queue = new ArrayDeque<>();
// offer() - 入队
queue.offer("Alice");
queue.offer("Bob");
queue.offer("Charlie");
System.out.println("Queue after offers: " + queue); // [Alice, Bob, Charlie]
// peek() - 查看队头
System.out.println("Front element (peek): " + queue.peek()); // Alice
System.out.println("Queue after peek: " + queue); // [Alice, Bob, Charlie] (不变)
// poll() - 出队
System.out.println("Polled element: " + queue.poll()); // Alice
System.out.println("Queue after poll: " + queue); // [Bob, Charlie]
}
}
三、总结与对比
1. 方法对比速查表
| 操作 | 栈 (Stack) | 队列 (Queue) |
|---|---|---|
| 添加元素 | push(e) |
offer(e) |
| 移除并返回元素 | pop() |
poll() |
| 查看元素 (不移除) | peek() |
peek() |
| 操作位置 | 尾部 (Tail) | 尾部添加 (Tail), 头部移除 (Head) |
| 遵循原则 | LIFO (后进先出) | FIFO (先进先出) |
2. 为什么推荐使用 Deque 而不是 Stack?
Stack是遗留类:java.util.Stack继承自Vector,而Vector是一个同步类,所有方法都用synchronized修饰,在不需要线程安全的场景下会带来不必要的性能开销。DequeAPI 更清晰、功能更强大:Deque接口专门为双端队列设计,其方法名(push,pop,offer,poll)比Stack的方法名(push,pop,addElement,removeElement)更具表现力,并且可以轻松实现栈、队列或双端队列。- 现代集合框架的一部分:
Deque是 Java Collections Framework (JCF) 的标准部分,遵循了统一的设计模式,使用起来更一致。
3. 选择 ArrayDeque 还是 LinkedList?
- 优先选择
ArrayDeque:在绝大多数情况下,ArrayDeque的性能都优于LinkedList,因为它基于数组,内存是连续的,CPU 缓存友好。 - 考虑
LinkedList的情况:- 需要在队列的中间频繁进行插入或删除操作。
- 需要一个可以实现
List接口的队列(LinkedList同时实现了List和Deque)。
总之,记住这个黄金法则:在 Java 中,当你需要使用栈或队列时,请优先考虑使用 Deque 接口及其实现类 ArrayDeque。
更多推荐


所有评论(0)