ArrayDeque is a resizable array that supports fast insertion and removal at both ends, so it works as both a stack and a queue. The legacy Stack class is synchronized and extends Vector, which makes it slower and lets you break stack rules. LinkedList works too, but uses more memory per element and has worse cache performance.
Key Points: • Stack extends Vector, so every method is synchronized, and you can call get(index) or add(index, x), which breaks the stack abstraction. • The Javadoc of Stack itself recommends Deque<Integer> stack = new ArrayDeque<>() instead. • ArrayDeque: amortised O(1) push, pop, offer and poll at both ends, with no node objects. • LinkedList allocates a node for every element (about 24 extra bytes each), which costs memory and causes more garbage collection. • ArrayDeque doesn't allow null elements. LinkedList does. • Neither is thread-safe. For threads, use ConcurrentLinkedDeque or LinkedBlockingDeque.
Code Example:
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Queue;
import java.util.Stack;
public class DequeDemo {
public static void main(String[] args) {
// As a stack (LIFO)
Deque<String> stack = new ArrayDeque<>();
stack.push("A");
stack.push("B");
stack.push("C");
System.out.println("Stack pop: " + stack.pop() + ", peek: " + stack.peek());
// As a queue (FIFO)
Queue<String> queue = new ArrayDeque<>();
queue.offer("first");
queue.offer("second");
System.out.println("Queue poll: " + queue.poll());
// Legacy Stack lets you break the rules
Stack<String> legacy = new Stack<>();
legacy.push("A");
legacy.push("B");
legacy.add(0, "sneaky"); // insert at the bottom
System.out.println("Legacy Stack: " + legacy);
// Classic interview use: balanced brackets
System.out.println("Balanced: " + isBalanced("{[()]}") + ", " + isBalanced("{[(])}"));
}
static boolean isBalanced(String s) {
Deque<Character> st = new ArrayDeque<>();
for (char c : s.toCharArray()) {
if ("({[".indexOf(c) >= 0) st.push(c);
else if (st.isEmpty() || "({[".indexOf(st.pop()) != ")}]".indexOf(c)) return false;
}
return st.isEmpty();
}
}Output:
Stack pop: C, peek: B Queue poll: first Legacy Stack: [sneaky, A, B] Balanced: true, false
Good to Know: The balanced-brackets function in the example is itself a very common coding question. Mention that you would solve it with an ArrayDeque, not Stack. It shows you know both the algorithm and the modern API.
Interview Tip: A concise interview answer is:
"I use ArrayDeque for both stacks and queues. Stack is a legacy class that extends Vector, so every call is synchronized and it even allows inserting in the middle, and LinkedList allocates a node per element, which wastes memory. ArrayDeque gives amortised O(1) operations at both ends with better cache performance; the only catch is that it doesn't allow nulls."
Previous question: Which Map methods added in Java 8 should every developer know?
Next question: How does PriorityQueue work, and how do you use it to find the top K elements?