java.util.Stack<E> 繼承自 Vector<E>,實現後進先出(LIFO)棧語義。雖然官方建議改用 Deque 介面(ArrayDeque),但 Stack 仍廣泛存在於歷史程式碼中。
| 方法 | 說明 | 異常情況 |
|---|---|---|
push(E item) | 壓入棧頂 | 無 |
pop() | 移除並回傳棧頂元素 | 空棧拋出 EmptyStackException |
peek() | 查看棧頂元素不移除 | 空棧拋出 EmptyStackException |
empty() | 判斷棧是否為空 | 回傳 boolean |
search(Object o) | 從棧頂向下搜尋,回傳 1-based 位置 | 未找到回傳 -1 |
package com.test;
import java.util.*;
public class Demo7_3 {
public static void main(String[] args) {
Emp emp = new Emp("sa001", "xiaoming", 12.3f);
Stack<Emp> stack = new Stack<>(); // 建議使用泛型
stack.push(emp); // 推薦用 push() 而非 add()
// 遍歷棧(注意:棧不支援高效隨機存取)
for (int i = 0; i < stack.size(); i++) {
Emp temp = stack.get(i); // 繼承自 Vector 的 get()
System.out.println("員工姓名:" + temp.getName());
}
}
}
// 員工實體類別
class Emp {
private String empNo;
private String name;
private float sal;
public Emp(String empNo, String name, float sal) {
this.empNo = empNo;
this.name = name;
this.sal = sal;
}
// Getter/Setter 省略
public String getName() { return name; }
public float getSal() { return sal; }
}
Stack 經典用途:算術表達式解析
public static int evaluatePostfix(String postfix) {
Stack<Integer> stack = new Stack<>();
for (String token : postfix.split(" ")) {
if (isOperator(token)) {
int b = stack.pop(), a = stack.pop();
stack.push(applyOperator(a, b, token));
} else {
stack.push(Integer.parseInt(token));
}
}
return stack.pop();
}
JDK 官方文件明確建議:
"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."
// 推薦寫法
Deque<Emp> stack = new ArrayDeque<>();
stack.push(emp); // 壓入
Emp top = stack.pop(); // 彈出
Emp peek = stack.peek(); // 查看
ArrayDeque 優勢:非同步(無 synchronized 開銷)、陣列實作記憶體效率高、實作 Deque 介面功能更完整。
Stack<Emp> 避免型別轉換get(i) 效能差,棧語義僅應操作棧頂ConcurrentLinkedDeque 或自行同步Stack 實現經典 LIFO 語義,適合表達式求值、瀏覽器歷史、遞迴轉迭代等場景。新專案優先選用 ArrayDeque,維護舊代碼時理解其 Vector 繼承特性(同步、動態擴容)即可。掌握棧思維,解決大類遞迴與回溯問題。