Stack
The Legacy java.util.Stack Class
Basic java.util.Stack usage
import java.util.Stack; Stack<Integer> stack = new Stack<>(); stack.push(1); stack.push(2); stack.push(3); System.out.println(stack.peek()); // 3, top of the stack System.out.println(stack.pop()); // removes and returns 3 System.out.println(stack); // remaining: [1, 2]
3 3 [1, 2]
The Modern Alternative: ArrayDeque
Stack vs. ArrayDeque, side by side
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Stack;
// Legacy — works, but carries unneeded synchronization overhead
Stack<String> legacyStack = new Stack<>();
legacyStack.push("a");
legacyStack.push("b");
System.out.println(legacyStack.pop()); // "b"
// Modern — same LIFO behavior, no synchronization overhead
Deque<String> modernStack = new ArrayDeque<>();
modernStack.push("a");
modernStack.push("b");
System.out.println(modernStack.pop()); // "b"b b
Worked Example: Balanced Parentheses
A classic use case for a stack is checking whether a string of brackets is balanced. Every opening bracket gets pushed; every closing bracket pops the top and checks that it matches.
Checking balanced parentheses with ArrayDeque
import java.util.ArrayDeque;
import java.util.Deque;
public class BalancedParens {
static boolean isBalanced(String input) {
Deque<Character> stack = new ArrayDeque<>();
for (char c : input.toCharArray()) {
if (c == '(' || c == '[' || c == '{') {
stack.push(c);
} else if (c == ')' || c == ']' || c == '}') {
if (stack.isEmpty()) return false;
char open = stack.pop();
if ((c == ')' && open != '(') ||
(c == ']' && open != '[') ||
(c == '}' && open != '{')) {
return false;
}
}
}
return stack.isEmpty();
}
public static void main(String[] args) {
System.out.println(isBalanced("{[a + (b * c)] - 1}")); // true
System.out.println(isBalanced("(a + [b)]")); // false
}
}true false
Aspect | java.util.Stack | ArrayDeque as a stack |
|---|---|---|
Base class | Extends Vector | Implements Deque directly |
Synchronization | Every method synchronized (overhead even single-threaded) | Not synchronized |
Performance | Slower due to locking | Faster in typical use |
Status | Legacy, not recommended for new code | Recommended |
Null elements | Allowed | Not allowed |
Stack is LIFO: push() adds, pop() removes and returns the top, peek() inspects it
java.util.Stack extends Vector and synchronizes every method — unnecessary overhead for most code
ArrayDeque is the JDK-recommended modern replacement for stack behavior
Balanced-bracket checking is a classic, practical stack use case