Java栈的基本概念与特性
栈(Stack)作为一种重要的线性数据结构,其核心特性是“后进先出”(LIFO, Last In First Out),类似于现实生活中的物品堆叠,新元素始终从栈顶压入(push),而出栈(pop)操作也仅允许从栈顶移除元素,Java中并未直接提供名为“Stack”的内置数据结构(尽管存在java.util.Stack类,但已不推荐使用),而是更推荐使用Deque接口的实现类(如LinkedList或ArrayDeque)来模拟栈的行为,因为它们提供了更高效且灵活的操作方式。

Java中栈的两种实现方式
基于LinkedList实现
LinkedList类实现了Deque接口,支持在两端高效插入和删除元素,因此天然适合作为栈的实现,其核心操作包括:
- 压栈(push):通过
addFirst()或push()方法将元素添加到链表头部(栈顶)。 - 出栈(pop):通过
removeFirst()或pop()方法移除并返回链表头部的元素。 - 查看栈顶元素(peek):通过
getFirst()或peek()方法获取栈顶元素但不移除。
示例代码:
Deque<Integer> stack = new LinkedList<>(); stack.push(1); // 压栈,栈内: [1] stack.push(2); // 压栈,栈内: [2, 1] System.out.println(stack.pop()); // 出栈,输出2,栈内: [1] System.out.println(stack.peek()); // 查看栈顶,输出1,栈内: [1]
基于ArrayDeque实现
ArrayDeque是基于动态数组实现的双端队列,相比LinkedList,它在内存使用和性能上更具优势(尤其在元素数量较多时,避免了链表节点的额外开销),其操作方式与LinkedList类似,但底层扩容机制更高效(默认初始容量为16,扩容时按2倍增长)。
示例代码:

Deque<String> stack = new ArrayDeque<>();
stack.push("Java"); // 压栈
stack.push("Python"); // 压栈,栈内: ["Python", "Java"]
System.out.println(stack.pop()); // 出栈,输出"Python"
核心操作的时间复杂度分析
栈的效率主要取决于底层实现:
- 压栈(push):LinkedList和ArrayDeque均为O(1),因为仅需修改头指针或数组索引。
- 出栈(pop):同样为O(1),直接移除头元素或调整栈顶指针。
- 查看栈顶(peek):O(1),无需遍历,直接访问头元素。
- 判空(isEmpty):O(1),只需检查元素数量是否为0。
需要注意的是,若使用java.util.Stack(继承自Vector),其操作由于涉及同步锁(synchronized),性能会略低于非线程安全的LinkedList或ArrayDeque。
栈的实际应用场景
栈的结构特性使其在多个领域有广泛应用:
- 方法调用栈:JVM通过栈存储方法调用时的局部变量、操作数栈等信息,方法调用时压栈,返回时出栈。
- 表达式求值:如逆波兰表达式(后缀表达式)的计算,通过栈暂存操作数,遇到运算符时弹出操作数计算并压回结果。
- 括号匹配验证:如检查代码中、
[]、是否匹配,遇到左括号压栈,遇到右括号时弹出栈顶元素匹配。 - 浏览器历史记录:通过栈实现“前进”和“后退”功能,访问新页面压栈,后退时出栈。
总结与最佳实践
在Java中实现栈时,优先选择Deque接口的实现类:

- 非线程安全场景:推荐
ArrayDeque,性能更优且内存占用低;若需频繁在中间插入/删除元素(栈操作极少涉及),可选LinkedList。 - 线程安全场景:可通过
Collections.synchronizedDeque()包装ArrayDeque或LinkedList,避免直接使用java.util.Stack。
理解栈的LIFO特性和底层实现原理,有助于在算法设计(如深度优先搜索)和系统开发中灵活应用这一基础数据结构。



















