在Java中,Stack是继承自Vector的栈实现类,默认遵循后进先出的操作规则,提供了完整的栈操作相关方法,适合在需要栈结构的场景中使用。Stack位于java.util包下,使用前需要先导入对应的类。

Stack的基本操作
1. 创建Stack实例
创建Stack实例的方式非常简单,直接通过无参构造方法即可完成初始化,泛型可以指定栈中存储的元素类型,避免后续类型转换的问题。
import java.util.Stack;
public class StackDemo {
public static void main(String[] args) {
// 创建一个存储整型的栈
Stack<Integer> stack = new Stack<>();
}
}
2. 入栈操作
入栈即把元素添加到栈的顶部,Stack提供了push方法完成该操作,方法会返回被添加的元素本身。
import java.util.Stack;
public class StackDemo {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
// 入栈操作,依次添加1、2、3
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(stack); // 输出[1, 2, 3]
}
}
3. 出栈操作
出栈即移除栈顶的元素并返回该元素,Stack提供了pop方法实现该功能,如果栈为空调用该方法会抛出EmptyStackException异常。
import java.util.Stack;
public class StackDemo {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
stack.push(3);
// 出栈操作,依次取出3、2、1
int num1 = stack.pop();
int num2 = stack.pop();
int num3 = stack.pop();
System.out.println(num1); // 输出3
System.out.println(num2); // 输出2
System.out.println(num3); // 输出1
}
}
4. 查看栈顶元素
如果需要获取栈顶元素但不移除它,可以使用peek方法,该方法同样会在栈为空时抛出EmptyStackException异常。
import java.util.Stack;
public class StackDemo {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
// 查看栈顶元素,不会移除
int top = stack.peek();
System.out.println(top); // 输出20
System.out.println(stack.size()); // 输出2,栈元素数量不变
}
}
5. 判断栈是否为空
Stack提供了empty方法用于判断栈是否为空,返回值为布尔类型,为空时返回true,否则返回false。
import java.util.Stack;
public class StackDemo {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
System.out.println(stack.empty()); // 输出true
stack.push(5);
System.out.println(stack.empty()); // 输出false
}
}
6. 查找元素位置
search方法可以查找指定元素在栈中的位置,返回值为从栈顶开始计数的位置,栈顶元素位置为1,如果元素不存在则返回-1。
import java.util.Stack;
public class StackDemo {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
stack.push(30);
// 查找20的位置,从栈顶开始数,30是1,20是2
int pos = stack.search(20);
System.out.println(pos); // 输出2
// 查找不存在的元素
int pos2 = stack.search(40);
System.out.println(pos2); // 输出-1
}
}
Stack的使用注意事项
线程安全特性
Stack继承自Vector,而Vector的方法大多使用了synchronized关键字修饰,因此Stack是线程安全的,在多线程环境下可以直接使用,但是同步操作会带来一定的性能开销,如果是在单线程场景下使用,性能表现不如其他非线程安全的栈实现。
和Deque的区别
Java官方更推荐在需要栈结构时使用Deque接口的实现类比如ArrayDeque,而不是Stack。因为Stack继承自Vector,设计上不够合理,而Deque的接口定义更清晰,同时ArrayDeque的性能更好,单线程场景下优先选择ArrayDeque实现栈操作。
import java.util.ArrayDeque;
import java.util.Deque;
public class DequeStackDemo {
public static void main(String[] args) {
// 用Deque实现栈操作
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1);
stack.push(2);
System.out.println(stack.pop()); // 输出2
System.out.println(stack.peek()); // 输出1
}
}
空栈操作异常处理
在对空栈调用pop或者peek方法时,会抛出EmptyStackException异常,因此在实际开发中,调用这两个方法前最好先通过empty方法判断栈是否为空,避免程序出现异常中断。
import java.util.Stack;
public class SafeStackDemo {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
// 先判断栈是否为空再操作
if (!stack.empty()) {
int num = stack.pop();
} else {
System.out.println("栈为空,无法执行出栈操作");
}
}
}
常见使用场景
Stack在很多业务场景中都有应用,比如括号匹配校验、表达式求值、浏览器的前进后退功能、深度优先搜索算法等。以下是一个简单的括号匹配校验示例,使用Stack实现:
import java.util.Stack;
public class BracketMatch {
public static boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) {
if (c == '(' || c == '[' || c == '{') {
// 左括号入栈
stack.push(c);
} else {
// 右括号先判断栈是否为空
if (stack.empty()) {
return false;
}
char top = stack.pop();
// 校验括号是否匹配
if (c == ')' && top != '(') {
return false;
}
if (c == ']' && top != '[') {
return false;
}
if (c == '}' && top != '{') {
return false;
}
}
}
// 最后栈为空说明所有括号都匹配
return stack.empty();
}
public static void main(String[] args) {
System.out.println(isValid("()[]{}")); // 输出true
System.out.println(isValid("(]")); // 输出false
}
}