棧 是「後進先出」(LIFO) 的線性表,僅允許在棧頂進行插入與刪除。本文展示三種經典實現:單向鏈表、動態陣列、委託 LinkedList,附完整代碼、複雜度分析、擴容策略、泛型支援與生產級建議。
public interface Stack {
int size();
boolean isEmpty();
void push(E element);
E pop();
E peek();
}
public class LinkedStack implements Stack {
private static class Node {
E element;
Node next;
Node(E e, Node n) { element = e; next = n; }
}
private Node top = null;
private int size = 0;
@Override public int size() { return size; }
@Override public boolean isEmpty() { return size == 0; }
@Override public void push(E element) {
top = new Node<>(element, top); // 新節點指向舊 top,再更新 top
size++;
}
@Override public E pop() {
if (isEmpty()) throw new EmptyStackException();
E result = top.element;
top = top.next; // 移除頂節點
size--;
return result;
}
@Override public E peek() {
if (isEmpty()) throw new EmptyStackException();
return top.element;
}
}
public class ArrayStack implements Stack {
private static final int DEFAULT_CAPACITY = 16;
private Object[] elements;
private int top = 0; // 指向下一個可寫入位置,同時也是 size
public ArrayStack() { this(DEFAULT_CAPACITY); }
public ArrayStack(int capacity) { elements = new Object[capacity]; }
@Override public int size() { return top; }
@Override public boolean isEmpty() { return top == 0; }
@Override public void push(E element) {
ensureCapacity(top + 1);
elements[top++] = element;
}
@SuppressWarnings("unchecked")
@Override public E pop() {
if (isEmpty()) throw new EmptyStackException();
E result = (E) elements[--top];
elements[top] = null; // 釋放引用,助 GC
return result;
}
@SuppressWarnings("unchecked")
@Override public E peek() {
if (isEmpty()) throw new EmptyStackException();
return (E) elements[top - 1];
}
private void ensureCapacity(int minCapacity) {
if (minCapacity <= elements.length) return;
int newCap = Math.max(elements.length * 2, minCapacity);
elements = Arrays.copyOf(elements, newCap);
}
}
addFirst/removeFirst/getFirst 皆 O(1)。@SuppressWarnings。
public class DelegatedStack implements Stack {
private final Deque deque = new LinkedList<>(); // Deque 介面語義更精確
@Override public int size() { return deque.size(); }
@Override public boolean isEmpty() { return deque.isEmpty(); }
@Override public void push(E element) { deque.addFirst(element); }
@Override public E pop() { return deque.removeFirst(); }
@Override public E peek() { return deque.getFirst(); }
}
Collections.synchronizedDeque) |
new ArrayStack<>() + ReentrantLock,或用 ConcurrentLinkedDeque 實現無鎖棧。ArrayStack 加 maxCapacity 參數,防止惡意/錯誤導致 OOM。Serializable,ArrayStack 需標記 elements 為 transient 並自定義 writeObject/readObject。Iterable,從棧頂到棧底遍歷 (不修改結構)。ConcurrentLinkedDeque 或 自己寫 Treiber Stack (CAS 無鎖演算法)。
// 現代 Java 最推薦的棧實現 (單執行緒)
Deque stack = new ArrayDeque<>();
stack.push("a");
stack.push("b");
stack.pop(); // "b"
stack.peek(); // "a"
ArrayDeque 以環狀陣列實現雙端隊列,**無容量上限 (自動擴容)、無節點物件、O(1) 雙端操作**,完美替代 Stack (舊類、繼承 Vector、同步開銷大) 與 LinkedList。