Queue, Deque, and ArrayDeque
Master Java's queue abstractions for FIFO processing, double-ended operations, and stack replacement. Learn why ArrayDeque outperforms both LinkedList and Stack, and when to use each queue variant.
📋 At a Glance
| Aspect | Details |
|---|---|
| Topic | Queue, Deque, ArrayDeque, LinkedList as Queue |
| Complexity | Intermediate |
| Prerequisites | Part 1 (Framework Architecture), Part 7 (LinkedList) |
| Time to Master | 2-3 hours |
| Interview Frequency | High (Queue operations, Stack replacement) |
🎯 What You'll Learn
After completing this article, you will be able to:
- Understand Queue and Deque interfaces and their operation pairs
- Master ArrayDeque's circular buffer implementation
- Replace deprecated Stack with ArrayDeque
- Choose between ArrayDeque and LinkedList for queue operations
- Implement BFS, undo/redo, and other classic patterns
Production Story: The Stack Overflow That Wasn't
The Incident
StackOverflowError - but not the JVM stack kind. We were using Java's Stack class and hitting unexpected performance issues:JAVA(18 lines)CodeLoading syntax highlighter...
The Problem with Stack
JAVA(14 lines)CodeLoading syntax highlighter...
The ArrayDeque Solution
JAVA(18 lines)CodeLoading syntax highlighter...
Performance Comparison
JAVA(15 lines)CodeLoading syntax highlighter...
Lessons Learned
- Never use Stack class - it's a legacy class from Java 1.0
- ArrayDeque is the modern replacement for both Stack and Queue
- Synchronization has cost - don't pay for it when you don't need it
- Check for legacy classes - Vector, Stack, Hashtable are outdated
Mental Model: The Double-Ended Line
TEXT(42 lines)CodeLoading syntax highlighter...
Deep Dive: Queue Interface
Queue Method Pairs
JAVA(11 lines)CodeLoading syntax highlighter...
When to Use Which
JAVA(20 lines)CodeLoading syntax highlighter...
Deep Dive: Deque Interface
Double-Ended Operations
JAVA(28 lines)CodeLoading syntax highlighter...
Deque as Stack vs Queue
JAVA(13 lines)CodeLoading syntax highlighter...
Deep Dive: ArrayDeque Internals
Circular Buffer Implementation
JAVA(20 lines)CodeLoading syntax highlighter...
Visual: Circular Buffer
TEXT(33 lines)CodeLoading syntax highlighter...
Resize Strategy
JAVA(17 lines)CodeLoading syntax highlighter...
Why No Nulls?
JAVA(6 lines)CodeLoading syntax highlighter...
Deep Dive: ArrayDeque vs LinkedList
Performance Comparison
| Operation | ArrayDeque | LinkedList |
|---|---|---|
| addFirst/addLast | O(1)* | O(1) |
| removeFirst/removeLast | O(1) | O(1) |
| get(index) | N/A | O(n) |
| Memory per element | ~8 bytes | ~40 bytes |
| Cache locality | Excellent | Poor |
| Null elements | Not allowed | Allowed |
*Amortized O(1) for ArrayDeque (occasional resize)
When to Use Which
JAVA(15 lines)CodeLoading syntax highlighter...
BFS Example: ArrayDeque vs LinkedList
JAVA(24 lines)CodeLoading syntax highlighter...
Deep Dive: Common Patterns
Pattern 1: Sliding Window
JAVA(22 lines)CodeLoading syntax highlighter...
Pattern 2: Undo/Redo Stack
JAVA(27 lines)CodeLoading syntax highlighter...
Pattern 3: Monotonic Deque (Sliding Window Maximum)
JAVA(24 lines)CodeLoading syntax highlighter...
Pattern 4: Level-Order Tree Traversal
JAVA(22 lines)CodeLoading syntax highlighter...
⚠️ Common Mistakes
Mistake 1: Using Stack Instead of ArrayDeque
JAVA(9 lines)CodeLoading syntax highlighter...
Mistake 2: Adding Null to ArrayDeque
JAVA(11 lines)CodeLoading syntax highlighter...
Mistake 3: Confusing add/offer Behavior
JAVA(12 lines)CodeLoading syntax highlighter...
Mistake 4: Wrong Direction for Stack Operations
JAVA(12 lines)CodeLoading syntax highlighter...
Mistake 5: Modifying During Iteration
JAVA(19 lines)CodeLoading syntax highlighter...
🐛 Debug This
Challenge 1: The Disappearing Elements
JAVA(9 lines)CodeLoading syntax highlighter...
Output:
TEXT(2 lines)CodeLoading syntax highlighter...
offeradds to tail: [1, 2, 3]pushadds to head: [0, 1, 2, 3]poll(= pollFirst) removes from head: returns 0, deque is [1, 2, 3]pollLastremoves from tail: returns 3, deque is [1, 2]
Challenge 2: The Iterator Direction
JAVA(15 lines)CodeLoading syntax highlighter...
Output:
TEXT(2 lines)CodeLoading syntax highlighter...
- addLast("A"): [A]
- addFirst("B"): [B, A]
- addLast("C"): [B, A, C]
- iterator(): head to tail → B A C
- descendingIterator(): tail to head → C A B
Challenge 3: The Queue vs Stack
JAVA(14 lines)CodeLoading syntax highlighter...
4 3 1 2- offer(1): [1]
- offer(2): [1, 2]
- push(3): [3, 1, 2]
- push(4): [4, 3, 1, 2]
- poll removes from head: 4, 3, 1, 2
💻 Exercises
Exercise 1: Browser History
Implement browser back/forward using two stacks:
JAVA(6 lines)CodeLoading syntax highlighter...
JAVA(33 lines)CodeLoading syntax highlighter...
Exercise 2: Valid Parentheses
Check if brackets are balanced:
JAVA(6 lines)CodeLoading syntax highlighter...
JAVA(15 lines)CodeLoading syntax highlighter...
Exercise 3: Recent Counter
Count requests in last 3000ms:
JAVA(8 lines)CodeLoading syntax highlighter...
JAVA(11 lines)CodeLoading syntax highlighter...
Exercise 4: Implement Queue Using Stacks
Implement FIFO queue using only stack operations:
JAVA(6 lines)CodeLoading syntax highlighter...
JAVA(31 lines)CodeLoading syntax highlighter...
Exercise 5: Circular Buffer
Implement a fixed-size circular buffer:
JAVA(7 lines)CodeLoading syntax highlighter...
JAVA(40 lines)CodeLoading syntax highlighter...
🎤 Senior-Level Interview Questions
Question 1: Stack vs ArrayDeque
- No synchronization overhead: Stack extends Vector, all methods synchronized
- Better performance: ArrayDeque is ~3-5x faster for push/pop
- Consistent API: Stack extends Vector, mixing stack and list semantics
- Modern design: ArrayDeque designed for Deque interface
JAVA(8 lines)CodeLoading syntax highlighter...
Question 2: ArrayDeque Null Restriction
- Ambiguity with poll(): poll() returns null for empty queue - can't distinguish stored null
- Efficient empty slot detection: Uses null to identify unused array slots
- Design decision: Cleaner API, prevents NPE bugs
JAVA(4 lines)CodeLoading syntax highlighter...
Question 3: Circular Buffer Benefits
Simple array approach:
JAVA(2 lines)CodeLoading syntax highlighter...
Circular buffer approach:
JAVA(5 lines)CodeLoading syntax highlighter...
Benefits:
- O(1) add/remove at both ends
- No shifting required
- Minimal memory overhead
- Excellent cache locality
Question 4: Queue vs Deque Interface
JAVA(14 lines)CodeLoading syntax highlighter...
Question 5: BFS Queue Choice
- Cache locality: ArrayDeque stores elements contiguously
- Memory efficiency: ~8 bytes/element vs ~40 bytes for LinkedList nodes
- No allocation per element: LinkedList creates node object for each add
- Faster operations: No pointer traversal
JAVA(4 lines)CodeLoading syntax highlighter...
Question 6: offer() vs add()
JAVA(14 lines)CodeLoading syntax highlighter...
📝 Summary & Key Takeaways
Queue Interface
- Two operation styles: throwing (add/remove/element) vs special-value (offer/poll/peek)
- Use offer/poll for normal empty/full handling
- Use add/remove when empty/full is a bug
Deque Interface
- Double-ended: addFirst/addLast, pollFirst/pollLast
- Stack: push/pop/peek (all operate on head)
- Queue: offer/poll (tail to head)
ArrayDeque
- Circular buffer - O(1) operations at both ends
- No null elements allowed
- Better than Stack and usually better than LinkedList
- Use for stack, queue, or deque operations
Best Practices
- Never use Stack class - use ArrayDeque
- Prefer ArrayDeque over LinkedList for queues
- Use most restrictive interface type (Queue vs Deque)
- Consider bounded queues for backpressure
🏁 Conclusion
ArrayDeque is the Swiss Army knife of Java's queue implementations. Understanding its circular buffer design explains why it outperforms alternatives and why it prohibits nulls. Whether you need a stack, queue, or double-ended queue, ArrayDeque should be your default choice.
Key takeaways:
- Never use Stack - ArrayDeque is faster and cleaner
- ArrayDeque's circular buffer enables O(1) operations at both ends
- No nulls allowed - uses null for empty slot detection
- Prefer ArrayDeque over LinkedList for pure queue/stack usage
- Interface choice matters - Queue restricts API, Deque exposes all operations
In the next article, we'll explore PriorityQueue and heap-based data structures - essential for scheduling, top-K problems, and priority-based processing.
📅 Review Schedule
To solidify your understanding, review this material:
- Tomorrow: Implement Exercise 4 (Queue using Stacks) from memory
- In 3 days: Explain ArrayDeque circular buffer to a colleague
- In 1 week: Review Stack class deprecation reasons
- In 2 weeks: Practice sliding window problems using Deque