The ArrayDeque Class
Objective
Understand ArrayDeque, a resizable-array Deque implementation with no capacity restriction — usable as a stack (LIFO, via push/pop) or a queue (FIFO, via offer/poll), and generally the JDK-recommended choice over the legacy Stack class or a LinkedList for either role.
Use Cases
- Implementing a stack without reaching for the legacy, synchronized
Stackclass. - Implementing a FIFO queue without
LinkedList's per-node allocation overhead. - Double-ended workloads that push/pop or add/remove from both ends.
- A resizable buffer with no fixed capacity, unlike bounded
Dequeimplementations.
Deep Dive
ArrayDeque extends AbstractCollection
javaclass ArrayDeque<E>Implements Deque<E> and adds no methods of its own — everything it offers comes from Deque. Three constructors:
javaArrayDeque<String> a = new ArrayDeque<>(); // empty, capacity sufficient for 16 elements
ArrayDeque<String> b = new ArrayDeque<>(100); // pre-sized for 100 elements
ArrayDeque<String> c = new ArrayDeque<>(List.of("x", "y")); // initialized from a collectionCapacity grows automatically as elements are added — Deque permits capacity-restricted implementations, but ArrayDeque isn't one of them.
Using it as a stack
javaArrayDeque<String> stack = new ArrayDeque<>();
stack.push("A"); stack.push("B"); stack.push("D"); stack.push("E"); stack.push("F");
while (stack.peek() != null) {
System.out.print(stack.pop() + " "); // F E D B A — last pushed, first popped
}push/pop are Deque's stack-oriented aliases for addFirst/removeFirst.
Watch it happen: push() building a stack
Each push() lands at the front — slot 0 below is the top of the stack, the next pop() target:
No collisions here, unlike a hash table — every push gets its own slot, and the last one in (F) sits at slot 0, exactly where pop() reads from first.
Using it as a queue
javaArrayDeque<String> queue = new ArrayDeque<>();
queue.offer("A"); queue.offer("B"); queue.offer("C");
queue.poll(); // "A" — first offered, first polledoffer/poll here work identically to the Queue methods described in the Queue interface concept — ArrayDeque satisfies Queue through Deque.
Trade-offs
nullelements are prohibited (NullPointerExceptionon insert) — unlikeLinkedList, which permitsnullsince it isn't dedicated solely toDeque-style usage:javaArrayDeque<String> dq = new ArrayDeque<>(); dq.add(null); // NullPointerExceptionNo capacity restriction and no blocking behavior — if a bounded, backpressure-producing queue is the actual requirement,
ArrayDequeis the wrong tool; that's what capacity-restricted implementations likeArrayBlockingQueueare for.Not synchronized — same caveat as every other class covered here; concurrent access from multiple threads needs external synchronization or a concurrent collection instead.
Array-backed storage avoids
LinkedList's per-node allocation, which is why the JDK documentation recommendsArrayDequeoverLinkedListfor stack/queue use whennullelements aren't needed — the trade-off is the same amortized-resize costArrayListpays, in exchange for no per-element node overhead.