java.util.Stack 繼承自 Vector,實現經典的後進先出(LIFO)數據結構。雖屬舊集合框架,但其語義清晰、API 簡單,在表達式求值、括號匹配、遞歸回溯等場景仍具教學與實用價值。本文詳解五大核心方法、源碼實現機制及現代替代方案。
public class Stack extends Vector {
// 唯一構造器:創建空棧
public Stack() { }
}
繼承 Vector 意味著:
Vector 方法可用(如 get()、size()、contains())| 方法 | 簽名 | 行為 | 異常 | 時間複雜度 |
|---|---|---|---|---|
| push | E push(E item) | 元素入棧(棧頂),返回該元素 | 無 | O(1) 攤銷 |
| pop | E pop() | 移除並返回棧頂元素 | EmptyStackException | O(1) |
| peek | E peek() | 查看棧頂元素,不移除 | EmptyStackException | O(1) |
| empty | boolean empty() | 判斷棧是否為空 | 無 | O(1) |
| search | int search(Object o) | 從棧頂(1)向下查找,返回 1-based 索引,未找到返回 -1 | 無 | O(n) |
import java.util.Stack;
public class StackDemo {
static void showPush(Stack st, int a) {
st.push(a);
System.out.println("push(" + a + ") → stack: " + st);
}
static void showPop(Stack st) {
System.out.print("pop → ");
Integer a = st.pop();
System.out.println(a + " | stack: " + st);
}
public static void main(String[] args) {
Stack st = new Stack<>();
System.out.println("初始: " + st); // []
showPush(st, 42); // [42]
showPush(st, 66); // [42, 66]
showPush(st, 99); // [42, 66, 99]
showPop(st); // 99 → [42, 66]
showPop(st); // 66 → [42]
showPop(st); // 42 → []
try {
showPop(st); // 拋出 EmptyStackException
} catch (Exception e) {
System.out.println("empty stack");
}
}
}
初始: []
push(42) → stack: [42]
push(66) → stack: [42, 66]
push(99) → stack: [42, 66, 99]
pop → 99 | stack: [42, 66]
pop → 66 | stack: [42]
pop → 42 | stack: []
empty stack
public E push(E item) {
addElement(item); // Vector 末尾添加
return item;
}
public synchronized E pop() {
int len = size();
if (len == 0) throw new EmptyStackException();
E obj = elementAt(len - 1); // 獲取最後一個
removeElementAt(len - 1); // 刪除最後一個
return obj;
}
public synchronized int search(Object o) {
int i = lastIndexOf(o); // Vector 從尾部查找
if (i >= 0) return size() - i; // 轉為棧頂起始索引
return -1;
}
JDK 1.6+ 官方文檔明確建議:
"A more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class."
import java.util.ArrayDeque;
import java.util.Deque;
Deque stack = new ArrayDeque<>();
stack.push(1); // 入棧
stack.push(2);
int top = stack.peek(); // 查看頂部 2
int popped = stack.pop(); // 出棧 2
boolean empty = stack.isEmpty(); // false
Deque 接口,支持雙端操作Vector 同步開銷forEach、stream() 等現代 API| 場景 | 棧邏輯 | 關鍵操作 |
|---|---|---|
| 括號匹配驗證 | 遇左括號 push,遇右括號 pop 比對 | push, pop, peek |
| 中綴轉後綴表達式 | 運算符優先級比較,輸出隊列 | push, pop, peek |
| 後綴表達式求值 | 操作數 push,運算符 pop 兩數計算再 push | push, pop |
| 瀏覽器前進/後退 | 兩個棧分別記錄歷史與未來 | push, pop |
| 遞歸算法模擬 | 手動維護調用棧幀 | push, pop, peek |
Stack 提供經典 LIFO 語義,五大方法 push/pop/peek/empty/search 覆蓋核心需求Vector 帶來線程安全但性能代價,新項目首選 ArrayDequesearch 的 1-based 從棧頂索引規則,避免 off-by-one 錯誤