它们最核心的区别在于 数据的存取顺序。

- 栈:遵循 后进先出 的原则,就像一摞盘子,你最后放上去的盘子,会最先被拿走。
- 队列:遵循 先进先出 的原则,就像排队买票,排在最前面的人最先买到票,离开队伍。
下面我们从多个维度进行详细的对比。
核心对比表格
| 特性 | 栈 | 队列 |
|---|---|---|
| 数据存取顺序 | LIFO (Last-In, First-Out) 后进先出 |
FIFO (First-In, First-Out) 先进先出 |
| 主要操作 | push (入栈), pop (出栈) |
enqueue (入队), dequeue (出队) |
| 操作位置 | 所有操作都在 同一端 进行(称为栈顶) | 操作在 两端 进行(一端入队,一端出队) |
| 类比现实 | 一摞盘子、子弹夹、函数调用栈 | 排队买票、打印任务队列 |
| 应用场景 | 括号匹配、表达式求值、函数调用、撤销操作 | 消息队列、任务调度、广度优先搜索 |
| Java 实现方式 | java.util.Stack (已过时,不推荐)java.util.LinkedListjava.util.ArrayDeque (推荐) |
java.util.LinkedListjava.util.ArrayDeque (推荐)java.util.PriorityQueue (优先级队列) |
详细解释
数据存取顺序
这是两者最根本的区别。
-
栈:
- 后进先出:想象一个只能从顶部开口的箱子,你最后放进去的物品,会最先被拿出来。
- 操作端:只有一个操作端,称为 栈顶,所有的添加和删除操作都只能在栈顶完成。
-
队列:
(图片来源网络,侵删)- 先进先出:想象一个只有一个入口和一个出口的管道,你从入口放进去的球,会按照放入的顺序从出口滚出来。
- 操作端:有两个操作端,一端称为 队尾,用于添加元素(入队);另一端称为 队头,用于移除元素(出队)。
主要操作
| 数据结构 | 添加元素 | 移除元素 | 查看顶端/队首元素 |
|---|---|---|---|
| 栈 | push(element) |
pop() |
peek() |
| 队列 | offer(element) / add(element) |
poll() / remove() |
peek() |
-
push/pop/peek(Stack):push(E e): 将元素压入栈顶。pop(): 弹出并返回栈顶的元素,如果栈为空,会抛出EmptyStackException。peek(): 查看栈顶的元素,但不移除它,如果栈为空,会抛出EmptyStackException。
-
offer/poll/peek(Queue):offer(E e): 将元素添加到队尾,如果成功,返回true;如果队列已满(对于有容量限制的队列),返回false,这是推荐使用的安全方法。poll(): 移除并返回队头的元素,如果队列为空,返回null,这是推荐使用的安全方法。peek(): 查看队头的元素,但不移除它,如果队列为空,返回null。
注意:
Queue接口也提供了add(),remove(),element()方法,它们的功能与offer(),poll(),peek()类似,但在操作失败时会抛出异常而不是返回null。
Java 中的实现方式
在 Java 中,栈和队列都不是独立的类,它们是接口,我们需要通过具体的类来实现它们。

如何实现一个栈?
不推荐:java.util.Stack
- 这是一个古老的类,继承自
Vector。 - 它是 线程同步 的,这意味着有性能开销。
- 它暴露了很多
Vector的方法(如get(),set()),破坏了栈“只操作栈顶”的原则,不安全。 - 除非有特殊需求,否则应避免使用
java.util.Stack。
推荐:java.util.ArrayDeque
ArrayDeque是一个基于数组的双端队列实现,性能非常出色。- 它实现了
Deque接口,而Deque(Double-Ended Queue) 接口扩展了Queue接口,并提供了push()和pop()方法来模拟栈的行为。 - 优点:性能高(无锁,非线程同步)、内存效率高。
示例代码:
import java.util.ArrayDeque;
import java.util.Deque; // Deque 是双端队列接口
public class StackExample {
public static void main(String[] args) {
// 使用 ArrayDeque 作为栈
Deque<String> stack = new ArrayDeque<>();
// push 操作 (入栈)
stack.push("Apple");
stack.push("Banana");
stack.push("Cherry");
System.out.println("Stack: " + stack); // 输出: [Cherry, Banana, Apple]
// peek 操作 (查看栈顶)
String top = stack.peek();
System.out.println("Top element: " + top); // 输出: Cherry
// pop 操作 (出栈)
String popped = stack.pop();
System.out.println("Popped element: " + popped); // 输出: Cherry
System.out.println("Stack after pop: " + stack); // 输出: [Banana, Apple]
}
}
如何实现一个队列?
推荐:java.util.ArrayDeque
- 和用作栈一样,
ArrayDeque也是实现队列的首选。 - 它提供了
offer()(入队),poll()(出队),peek()(查看队首) 等方法。 - 优点:性能高,是大多数场景下的默认选择。
备选:java.util.LinkedList
LinkedList实现了List和Deque接口,因此它天生就可以作为队列使用。- 当队列中元素数量变化很大,或者需要频繁在中间插入/删除时,
LinkedList可能比ArrayDeque表现更好。 - 缺点:相比
ArrayDeque,它的内存占用稍高,且性能不如ArrayDeque稳定。
示例代码:
import java.util.ArrayDeque;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
// 使用 ArrayDeque 作为队列
Queue<String> queue = new ArrayDeque<>();
// offer 操作 (入队)
queue.offer("Person 1");
queue.offer("Person 2");
queue.offer("Person 3");
System.out.println("Queue: " + queue); // 输出: [Person 1, Person 2, Person 3]
// peek 操作 (查看队首)
String front = queue.peek();
System.out.println("Front element: " + front); // 输出: Person 1
// poll 操作 (出队)
String served = queue.poll();
System.out.println("Served element: " + served); // 输出: Person 1
System.out.println("Queue after poll: " + queue); // 输出: [Person 2, Person 3]
}
}
应用场景举例
栈 的应用场景
- 函数调用栈:当你调用一个函数时,它的返回地址、参数和局部变量会被压入调用栈,当函数返回时,这些信息会从栈中弹出,这是程序执行的基础。
- 括号匹配:在编译器或代码编辑器中,检查代码中的括号 ,
[], 是否匹配,遇到左括号就压入栈,遇到右括号就弹出栈顶元素进行匹配。 - 表达式求值:在计算逆波兰表达式(后缀表达式)时,使用栈来存储操作数。
- 撤销/重做:文本编辑器的“撤销”功能通常用一个栈来保存用户的历史操作。
队列 的应用场景
- 消息队列:在分布式系统中,用于异步处理任务,一个服务将任务放入队列,另一个或多个工作服务从队列中取出任务来执行,实现了系统解耦和削峰填谷。
- 任务调度:操作系统中的进程调度、线程池中的任务管理,都使用队列来保证任务按顺序执行。
- 广度优先搜索:在图的遍历算法中,使用队列来存储待访问的节点,保证先访问离起点近的节点。
- 打印任务:打印机会将打印任务放入队列,按照先来后到的顺序依次打印。
| 栈 | 队列 | |
|---|---|---|
| 核心思想 | 后进先出 | 先进先出 |
| 操作口诀 | 后进先出,像一个死胡同 | 先进先出,像一条单行道 |
| Java 推荐实现 | ArrayDeque (作为 Deque 使用) |
ArrayDeque |
| 选择依据 | 当你需要处理“或“最新”的数据,并且需要快速获取和移除它时。 | 当你需要处理数据,并且必须按照它们到达的顺序进行处理时。 |
记住这个核心区别,你就能在合适的场景下选择正确的数据结构。
