在Java编程中,栈(Stack)作为一种重要的数据结构,遵循“后进先出”(LIFO)的原则,广泛应用于函数调用、表达式求值、括号匹配等场景,获取栈顶元素是栈操作中的基础且高频的需求,本文将系统介绍Java中获取栈顶元素的多种方法,结合代码示例与注意事项,帮助开发者全面掌握相关知识点。

使用Java集合框架中的Stack类
Java集合框架提供了java.util.Stack类,它是Vector类的子类,直接实现了栈的基本操作。Stack类提供了peek()方法专门用于获取栈顶元素,该方法不会移除栈顶元素,仅返回其值,以下是具体示例:
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
stack.push(30);
// 获取栈顶元素
int topElement = stack.peek();
System.out.println("栈顶元素: " + topElement); // 输出: 30
System.out.println("栈大小: " + stack.size()); // 输出: 3(peek不影响栈大小)
}
}
注意事项:
peek()方法在栈为空时会抛出EmptyStackException,因此在调用前需通过empty()方法检查栈是否为空。Stack类是线程安全的,但由于其继承自Vector,同步开销较大,在单线程环境下更推荐使用LinkedList或ArrayDeque实现栈。
基于LinkedList实现栈操作
LinkedList类实现了Deque接口,虽然它是一个双向链表,但通过调用push()(或addFirst())和peek()(或getFirst())方法,可以高效地实现栈操作,这种方式比Stack类更灵活且性能更优:
import java.util.LinkedList;
public class LinkedListStack {
public static void main(String[] args) {
LinkedList<Integer> stack = new LinkedList<>();
stack.push(10);
stack.push(20);
stack.push(30);
// 获取栈顶元素
int topElement = stack.peek();
System.out.println("栈顶元素: " + topElement); // 输出: 30
}
}
优势:
LinkedList的peek()方法在栈为空时返回null,而不会抛出异常,避免了额外的空检查。- 底层基于链表实现,插入和删除操作的时间复杂度为O(1),适合频繁的栈操作场景。
使用ArrayDeque实现栈
java.util.ArrayDeque是Java 6引入的双端队列实现,推荐作为栈的首选方案,它基于动态数组实现,相比LinkedList具有更低的内存开销和更快的访问速度:
import java.util.ArrayDeque;
public class ArrayDequeStack {
public static void main(String[] args) {
ArrayDeque<Integer> stack = new ArrayDeque<>();
stack.push(10);
stack.push(20);
stack.push(30);
// 获取栈顶元素
int topElement = stack.peek();
System.out.println("栈顶元素: " + topElement); // 输出: 30
}
}
关键点:

ArrayDeque的peek()方法同样在栈为空时返回null。- 初始容量默认为16,可通过构造方法指定初始容量,避免扩容带来的性能损耗。
- 不支持
null元素,若尝试插入null会抛出NullPointerException。
获取栈顶元素的其他方法
除了peek()方法,还可以通过以下方式获取栈顶元素,但需注意其行为差异:
-
使用
element()方法:- 与
peek()功能类似,但在栈为空时抛出NoSuchElementException。int topElement = stack.element();
- 与
-
通过索引访问(仅适用于Stack类):
Stack类继承自Vector,可通过get(size()-1)获取栈顶元素,但这种方式破坏了栈的封装性,不推荐使用。int topElement = stack.get(stack.size() - 1);
异常处理与最佳实践
在获取栈顶元素时,必须考虑栈为空的情况,以下是几种安全的处理方式:
-
使用
if语句检查栈是否为空:if (!stack.isEmpty()) { int top = stack.peek(); } else { System.out.println("栈为空,无法获取栈顶元素"); } -
利用
peek()返回null的特性(适用于LinkedList和ArrayDeque):
Integer top = stack.peek(); if (top != null) { System.out.println("栈顶元素: " + top); } -
使用
try-catch捕获异常(适用于Stack类):try { int top = stack.peek(); } catch (EmptyStackException e) { System.err.println("栈已空"); }
最佳实践总结:
- 优先选择
ArrayDeque或LinkedList实现栈,避免使用过时的Stack类。 - 在不确定栈是否为空时,始终使用
isEmpty()方法检查或处理peek()返回的null值。 - 避免通过索引直接访问栈元素,保持操作的封装性。
实际应用场景示例
在表达式求值中,栈常用于处理运算符优先级,以下是一个简化的中缀表达式转后缀表达式的示例,其中多次涉及获取栈顶元素的操作:
import java.util.ArrayDeque;
import java.util.Deque;
public class InfixToPostfix {
public static void main(String[] args) {
String expression = "a+b*c";
Deque<Character> stack = new ArrayDeque<>();
StringBuilder output = new StringBuilder();
for (char c : expression.toCharArray()) {
if (Character.isLetterOrDigit(c)) {
output.append(c);
} else if (c == '(') {
stack.push(c);
} else if (c == ')') {
while (!stack.isEmpty() && stack.peek() != '(') {
output.append(stack.pop());
}
stack.pop(); // 弹出'('
} else { // 运算符
while (!stack.isEmpty() && precedence(c) <= precedence(stack.peek())) {
output.append(stack.pop());
}
stack.push(c);
}
}
while (!stack.isEmpty()) {
output.append(stack.pop());
}
System.out.println("后缀表达式: " + output);
}
private static int precedence(char op) {
return switch (op) {
case '+', '-' -> 1;
case '*', '/' -> 2;
default -> -1;
};
}
}
通过上述示例可以看出,获取栈顶元素是算法实现中的关键步骤,直接影响到逻辑的正确性和效率。
在Java中获取栈顶元素的方法多种多样,开发者需根据具体场景选择合适的实现方式,无论是传统的Stack类,还是现代的ArrayDeque和LinkedList,理解其底层原理和异常处理机制是编写健壮代码的前提,通过合理选择数据结构和规范操作流程,可以高效、安全地完成栈顶元素的获取,为复杂问题的解决奠定坚实基础。


















