Queue & Deque
A Queue models first-in-first-out (FIFO) processing: elements are added at one end and removed from the other, in the same order they arrived — think of a line at a checkout counter. A Deque (short for "double-ended queue") generalizes that idea further, allowing insertion and removal at both ends, which makes it flexible enough to act as a queue, a stack, or something in between.
The Queue Interface
Queue is an interface, and the most common way to use it is through a variable typed as Queue pointing at a concrete implementation such as LinkedList or ArrayDeque. Elements go in at the tail and come out at the head.
Basic FIFO processing with a Queue
Java
import java.util.LinkedList;
import java.util.Queue;
Queue<String> ticketLine = new LinkedList<>();
ticketLine.offer("Alice");
ticketLine.offer("Bob");
ticketLine.offer("Charlie");
while (!ticketLine.isEmpty()) {
System.out.println("Now serving: " + ticketLine.poll());
}Now serving: Alice Now serving: Bob Now serving: Charlie
Two Method Families: Throwing vs. Safe
Queue actually offers two parallel sets of methods for the same three operations — insert, remove, and peek. One set throws an exception when something goes wrong (like removing from an empty queue); the other returns a special value (null or false) instead. Reaching for the wrong set in the wrong situation is a common source of unexpected NoSuchElementException crashes.
Operation | Throws on failure | Returns special value |
|---|---|---|
Insert | add(e) — throws if capacity-bounded and full | offer(e) — returns false if it can't be added |
Remove | remove() — throws NoSuchElementException if empty | poll() — returns null if empty |
Examine | element() — throws NoSuchElementException if empty | peek() — returns null if empty |
Tip
Prefer offer(), poll(), and peek() in everyday code — checking for null/false is usually easier to reason about than catching exceptions, especially inside a loop.
Deque — Both Ends
Deque extends the idea of a queue by exposing explicit "first" and "last" operations for both insertion and removal: addFirst()/addLast(), removeFirst()/removeLast(), and their offer/poll/peek counterparts. That flexibility means a single Deque can serve as either a queue or a stack, depending on which end you use.
Using a Deque from both ends
Java
import java.util.ArrayDeque; import java.util.Deque; Deque<Integer> deque = new ArrayDeque<>(); deque.addFirst(1); // [1] deque.addLast(2); // [1, 2] deque.addFirst(0); // [0, 1, 2] System.out.println(deque); System.out.println(deque.peekFirst()); System.out.println(deque.peekLast());
[0, 1, 2] 0 2
ArrayDeque — The Recommended Implementation
ArrayDeque is a resizable-array implementation of Deque, and it's the implementation recommended for both queue and stack use cases in modern Java. It has no capacity limits (it grows as needed), is generally faster than LinkedList for these purposes because it avoids the overhead of per-element node objects, and implements both the Queue and Deque interfaces — so it gives you FIFO behavior via offer()/poll() and LIFO (stack) behavior via push()/pop(), all from one class.
ArrayDeque as a queue and as a stack
Java
import java.util.ArrayDeque;
import java.util.Deque;
// Used as a FIFO queue
Deque<String> queue = new ArrayDeque<>();
queue.offer("first");
queue.offer("second");
System.out.println(queue.poll()); // "first" comes out first
// Used as a LIFO stack
Deque<String> stack = new ArrayDeque<>();
stack.push("first");
stack.push("second");
System.out.println(stack.pop()); // "second" comes out firstfirst second
Note
ArrayDeque does not allow null elements — inserting null throws a NullPointerException. This is intentional: it lets methods like poll() safely use null as an "empty" sentinel without any ambiguity.
Queue models FIFO processing: elements leave in the order they arrived
Each core operation has a throwing form and a safe form that returns null/false
Deque supports insertion and removal at both ends
ArrayDeque is the modern go-to implementation for both queue and stack needs