java集合-Stack
·
Stack 是 Java 中基于栈数据结构实现的集合类,核心特性是后进先出(LIFO, Last In First Out),也就是最后放入的元素最先被取出。
它继承自 Vector,是线程安全的集合,常用于方法调用栈、表达式求值、括号匹配、撤销操作等场景。
1.Stack 核心方法
Stack 提供了 5 个专用方法,完全满足栈的操作需求:
| 方法 | 作用 |
|---|---|
push(E item) | 入栈:将元素压入栈顶 |
pop() | 出栈:移除并返回栈顶元素(栈空会抛异常) |
peek() | 查看栈顶:返回栈顶元素但不移除(栈空会抛异常) |
empty() | 判空:栈为空返回 true,否则 false |
search(Object o) | 查找元素:返回元素距栈顶的位置(栈顶 = 1,找不到返回 - 1) |
2.基础使用实例
import java.util.Stack;
public class StackDemo {
public static void main(String[] args) {
// 1. 创建栈对象(存储字符串类型)
Stack<String> stack = new Stack<>();
// 2. push:元素入栈
stack.push("Java");
stack.push("Python");
stack.push("C++");
System.out.println("入栈后:" + stack); // [Java, Python, C++]
// 3. peek:查看栈顶元素(不删除)
System.out.println("栈顶元素:" + stack.peek()); // C++
// 4. pop:出栈(删除并返回栈顶)
String top = stack.pop();
System.out.println("出栈元素:" + top); // C++
System.out.println("出栈后:" + stack); // [Java, Python]
// 5. empty:判断栈是否为空
System.out.println("栈是否为空:" + stack.empty()); // false
// 6. search:查找元素位置(栈顶=1)
System.out.println("Java 位置:" + stack.search("Java")); // 2
System.out.println("Go 位置:" + stack.search("Go")); // -1(不存在)
}
}
运行结果
入栈后:[Java, Python, C++]
栈顶元素:C++
出栈元素:C++
出栈后:[Java, Python]
栈是否为空:false
Java 位置:2
Go 位置:-1
3.关键注意事项
1.栈空操作会抛异常
调用 pop()/peek() 时,如果栈为空,会抛出 EmptyStackException,建议先判空:
if (!stack.empty()) {
stack.pop();
}
2.线程安全但效率低
Stack 继承自 Vector,所有方法都加了 synchronized 锁,线程安全但性能较差。➡️ 推荐替代方案:单线程用 ArrayDeque,双端队列性能远超 Stack。
3.继承设计不推荐
Java 官方不推荐使用 java.util.Stack,更推荐用 Deque 接口实现栈:
// 官方推荐的栈写法(性能更好)
Deque<String> stack = new ArrayDeque<>();
4.源码
1.push(入栈)
逻辑:元素添加到数组最后一位(栈顶)
public E push(E item) {
addElement(item); // 调用 Vector 的方法,尾部追加元素
return item;
}
// Vector.addElement 底层:
// elementData[elementCount++] = obj;
2.pop(出栈)
逻辑:删除并返回数组最后一位,数组长度减 1
public synchronized E pop() { // 线程安全
int len = size();
E obj = peek(); // 获取栈顶
removeElementAt(len - 1); // 删除数组最后一个元素
return obj;
}
3.peek(查看栈顶)
逻辑:直接返回数组最后一位元素,不修改结构
public synchronized E peek() {
int len = size();
if (len == 0) throw new EmptyStackException();
return elementAt(len - 1); // 访问数组最后一位
}
4.empty(判空)
public boolean empty() {
return size() == 0; // 判断数组长度是否为0
}
5.search(查找元素)
逻辑:从栈顶(数组尾部)往栈底(数组头部)查找
public synchronized int search(Object o) {
int i = lastIndexOf(o); // 数组反向查找
if (i >= 0) return size() - i; // 返回栈中的位置(栈顶为1)
return -1;
}
6.底层数据结构图解
数组下标: 0 1 2 3 <-- 栈顶(push/pop/peek 都操作这里)
元素: [A] [B] [C] [D]
栈结构: 栈底 -> -> 栈顶
- 栈底 = 数组头部
- 栈顶 = 数组尾部
- 所有操作都是O (1) 时间复杂度(数组随机访问)
5.总结
1. 优点
- 实现简单,直接复用动态数组;
- 线程安全(所有读写方法加了
synchronized锁); - 自动扩容,无需手动管理容量。
2. 缺点(重要!开发不推荐使用)
- 性能差:锁机制导致多线程下效率低;
- 继承设计不合理:Stack 继承 Vector,暴露了大量非栈操作(如
add(int index)),破坏栈的封装性; - 官方不推荐:Java 官方明确建议使用
Deque替代 Stack。
更多推荐




所有评论(0)