Deque and ArrayDeque in Java – Stack + Queue in One

Illustration for Deque and ArrayDeque in Java – Stack + Queue in One
By Last updated:

In real-world Java development, data structures often need to support both stack (LIFO) and queue (FIFO) operations efficiently. This is where Deque (Double-Ended Queue) shines — a hybrid structure that allows insertions and deletions from both ends. ArrayDeque is its most widely used implementation, offering blazing-fast performance for both ends.

Whether you're building compilers, caching systems, or algorithmic solutions (like sliding window problems), mastering Deque and ArrayDeque is essential.


What Is Deque in Java?

Definition

A Deque (pronounced "deck") is a linear collection that supports insertion and removal of elements at both ends: front and rear.

Deque<String> deque = new ArrayDeque<>();

Key Features

  • Supports stack and queue operations.
  • Null elements are not allowed in ArrayDeque.
  • Efficient O(1) performance for add/remove operations at both ends.

ArrayDeque – Java’s Fastest Deque Implementation

Internal Working

  • Backed by a resizable circular array.
  • Automatically doubles in size when capacity is exceeded.
  • Uses two pointers: head and tail.
  • No thread-safety; prefer ConcurrentLinkedDeque for concurrency.

Memory Layout

   +-----------------------------------------+
   | null | A | B | C | null | null | null   |
   +-----------------------------------------+
           ↑           ↑
         head         tail

When resized, it wraps around to use all available space.


Java Syntax and Methods

Creating a Deque

Deque<Integer> deque = new ArrayDeque<>();

Common Operations

Operation Method Description
Add to front addFirst(e) Adds element to front
Add to rear addLast(e) Adds element to rear
Remove from front removeFirst() Removes and returns front element
Remove from rear removeLast() Removes and returns rear element
Peek front peekFirst() Views front element
Peek rear peekLast() Views rear element
Stack push push(e) Adds element to front (like a stack)
Stack pop pop() Removes and returns front (like a stack)

Code Example – Deque as Stack and Queue

Deque<String> deque = new ArrayDeque<>();

// Queue behavior (FIFO)
deque.addLast("A");
deque.addLast("B");
System.out.println(deque.removeFirst()); // A

// Stack behavior (LIFO)
deque.push("C");
deque.push("D");
System.out.println(deque.pop()); // D

Performance and Big-O

Operation Time Complexity
Add/Remove (head/tail) O(1)
Resize (amortized) O(n)
Search O(n)

Real-World Use Cases

  • Sliding window algorithms
  • Backtracking problems
  • Undo/redo stacks
  • Task schedulers
  • Browser history navigation

Comparisons

ArrayDeque vs LinkedList

Feature ArrayDeque LinkedList
Backing Resizable array Doubly linked list
Null allowed? ❌ No ✅ Yes
Memory usage Lower Higher
Random access ❌ No ❌ No
Thread-safe ❌ No ❌ No

Functional Programming Support

Deque<String> deque = new ArrayDeque<>(List.of("X", "Y", "Z"));

deque.stream()
     .filter(s -> s.contains("Y"))
     .forEach(System.out::println);

📌 What's New in Java Versions?

  • Java 8
    • Stream API compatible with Deque
    • Lambda-based filtering and iteration
  • Java 9
    • List.of(), Set.of() for factory methods (useful in initializing)
  • Java 10+
    • var for type inference: var dq = new ArrayDeque<String>();
  • Java 21
    • Improved memory optimizations for small collections

Anti-Patterns and Misuse Cases

  • Using ArrayDeque where thread-safety is required → prefer ConcurrentLinkedDeque
  • Adding null → throws NullPointerException
  • Treating Deque as purely FIFO or LIFO → underutilizes its capabilities

Refactoring Legacy Code

Before:

Stack<Integer> stack = new Stack<>();

After:

Deque<Integer> stack = new ArrayDeque<>();

ArrayDeque is preferred over Stack (which is synchronized and legacy).


Best Practices

  • Always prefer ArrayDeque over Stack
  • Avoid using null
  • Use Deque when you need both FIFO and LIFO operations
  • Use LinkedList only when frequent element removals in the middle are required

Conclusion & Key Takeaways

  • Deque is a versatile data structure combining features of both stack and queue.
  • ArrayDeque offers fast, memory-efficient implementation.
  • Avoid Stack and LinkedList unless necessary.
  • Leveraging Deque in modern Java improves clarity and performance.

FAQ – Advanced Concepts

1. Why use ArrayDeque over Stack?

Because Stack is synchronized and legacy. ArrayDeque is faster and recommended.

2. Is ArrayDeque thread-safe?

No. Use ConcurrentLinkedDeque for concurrent scenarios.

3. Can we add null to ArrayDeque?

No. Nulls are not allowed and throw NullPointerException.

4. What happens if capacity is exceeded?

Internally resizes (doubles in size).

5. What’s the initial capacity of an ArrayDeque?

Default is 16 (and grows as needed).

6. When is LinkedList better than ArrayDeque?

Only when you need frequent insertions/removals from middle of the list.

7. What is the backing data structure?

A resizable circular array.

8. What is Deque short for?

Double-Ended Queue.

9. Can I use Deque with Streams?

Yes, you can use any Collection with Stream API.

10. Is there a Deque for priority-based access?

No. Use PriorityQueue or TreeSet for sorted access.