By WebNest Studio Engineering Team
Java - Core Tutorial
Queue and Deque: PriorityQueue, ArrayDeque
Queue models a collection designed for holding elements before processing, typically in first-in-first-out (FIFO) order: elements are added at the tail with offer() and removed from the head with poll(). Deque ("double-ended queue") extends this idea, allowing efficient insertion and removal at both ends, which makes it flexible enough to act as a queue, a stack, or both.
Why it matters
Queues and stacks are how programs hold work that is waiting to be done: tasks for a thread pool, nodes still to visit in a graph search, operations that can be undone. ArrayDeque is the right class for both a stack and a plain queue, and PriorityQueue is the standard tool whenever the next item should be the smallest or the most urgent and not the oldest.
Queue Basics and Method Pairs
Queue offers two parallel sets of methods: one set throws an exception on failure (add(), remove(), element()), and one set returns a special value instead (offer(), poll(), peek()). The value-returning versions are generally preferred in everyday code, because they avoid unexpected exceptions when a queue is empty or full — poll() returns null instead of throwing when the queue is empty.
PriorityQueue — Ordering by Priority, Not Insertion
PriorityQueue does not preserve FIFO order; instead, it always returns the smallest element first according to natural ordering (via Comparable) or a supplied Comparator. Internally it is backed by a binary heap, giving O(log n) for offer() and poll(), and O(1) for peek() at the head. It does not permit null elements, since nulls cannot be compared. PriorityQueue is the standard tool for scheduling problems and "find the next most important item" logic.
Deque and ArrayDeque as a Modern Stack
Deque supports addFirst()/addLast(), removeFirst()/removeLast(), and peekFirst()/peekLast(), all in O(1) time on ArrayDeque, which is backed by a resizable circular array. Because a stack is just a deque used at one end (push()/pop()/peek() all operate on the head), the official Java documentation recommends ArrayDeque over the old Stack class: it is faster (no synchronization overhead), has no legacy baggage, and does not allow null elements, which catches bugs earlier than the historically permissive Stack class.
- Queue: FIFO by default; exception-throwing and value-returning method pairs.
- PriorityQueue: heap-based, O(log n) offer/poll, orders by Comparable or Comparator, no nulls.
- ArrayDeque: O(1) at both ends, preferred replacement for both Stack and LinkedList-as-queue.
Time complexity
| Operation | Average | Worst case |
|---|---|---|
| ArrayDeque add or remove at either end | O(1) | O(n) when the array must grow |
PriorityQueue offer, poll | O(log n) | O(log n) |
PriorityQueue peek | O(1) | O(1) |
PriorityQueue contains, remove(o) | O(n) | O(n) |
Example
PriorityQueue ordering versus ArrayDeque used as a stack and a queue
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.PriorityQueue;
import java.util.Queue;
public class QueueDeckDemo {
public static void main(String[] args) {
Queue<Integer> pq = new PriorityQueue<>();
pq.offer(30);
pq.offer(10);
pq.offer(20);
System.out.print("PriorityQueue polling order: ");
while (!pq.isEmpty()) {
System.out.print(pq.poll() + " "); // always smallest first: 10, 20, 30
}
System.out.println();
Deque<String> stack = new ArrayDeque<>();
stack.push("first");
stack.push("second");
stack.push("third");
System.out.println("Stack pop (LIFO): " + stack.pop()); // "third"
Deque<String> queue = new ArrayDeque<>();
queue.offer("first");
queue.offer("second");
System.out.println("Deque poll (FIFO): " + queue.poll()); // "first"
}
}
PriorityQueue polling order: 10 20 30
Stack pop (LIFO): third
Deque poll (FIFO): first
Where this is used
Breadth-first search uses a queue of nodes still to visit, and depth-first search uses a stack; both are normally an ArrayDeque. A PriorityQueue is behind Dijkstra's shortest-path algorithm, schedulers that run the earliest-due job first, and the common interview task of finding the top k items of a large collection.
Common Mistakes
- Assuming PriorityQueue.iterator() or toString() returns elements in sorted order — only repeated poll() calls guarantee sorted retrieval.
- Using the legacy Stack class for new code instead of ArrayDeque, missing out on better performance and no synchronization overhead.
- Adding a null element to a PriorityQueue or ArrayDeque, which throws NullPointerException immediately.
- Mixing up add()/remove() (throw exceptions) with offer()/poll() (return special values) and getting an unexpected exception on an empty queue.
Exercise
Use an ArrayDeque as a stack to check whether the brackets in a string are balanced. Each closing bracket must match the most recent opening bracket that is still open.
Expected output: true then false
import java.util.ArrayDeque;
import java.util.Deque;
public class Brackets {
static boolean balanced(String text) {
Deque<Character> stack = new ArrayDeque<>();
// TODO: push each opening bracket
// TODO: for each closing bracket, pop and check that it matches
return false; // TODO: balanced only if nothing is left open
}
public static void main(String[] args) {
System.out.println(balanced("{[()]}"));
System.out.println(balanced("([)]"));
}
}
Show hints
pushadds to the top of the stack andpopremoves from the top.- A closing bracket with an empty stack means the string is not balanced. Check
isEmpty()before callingpop.
Show solution
import java.util.ArrayDeque;
import java.util.Deque;
public class Brackets {
static boolean balanced(String text) {
Deque<Character> stack = new ArrayDeque<>();
for (char c : text.toCharArray()) {
if (c == '(' || c == '[' || c == '{') {
stack.push(c);
} else {
if (stack.isEmpty()) {
return false;
}
char open = stack.pop();
boolean matches = (open == '(' && c == ')')
|| (open == '[' && c == ']')
|| (open == '{' && c == '}');
if (!matches) {
return false;
}
}
}
return stack.isEmpty();
}
public static void main(String[] args) {
System.out.println(balanced("{[()]}")); // true
System.out.println(balanced("([)]")); // false
}
}
Quick quiz
1. What does poll() return when the queue is empty?
- A. It throws NoSuchElementException
- B. An empty Optional
- C. 0
- D. null
Show answer
D. poll() and peek() return null on an empty queue. remove() and element() throw.
2. The numbers 5, 1 and 3 are added to a PriorityQueue<Integer> in that order. What does the first poll() return?
- A. 5
- B. 3
- C. 1
- D. It depends on the JVM
Show answer
C. A PriorityQueue returns the smallest element first, by natural ordering, whatever the insertion order.
3. Which class is recommended for a stack in new code?
- A. Stack
- B. ArrayDeque
- C. Vector
- D. PriorityQueue
Show answer
B. Stack extends the legacy, synchronized Vector. ArrayDeque is faster and has push, pop and peek.
Interview questions
What is the difference between a Queue and a Deque?
Show answer
A Queue adds at one end and removes from the other, which gives first-in-first-out order. A Deque, a double-ended queue, can add and remove at both ends, so the same object can act as a queue or as a stack. ArrayDeque and LinkedList both implement Deque.
How does a PriorityQueue work internally?
Show answer
It is a binary heap stored in an array. The smallest element is always at the root, so peek is O(1). Adding an element or removing the root moves an element up or down the heap to restore the order, which is O(log n). The array as a whole is not sorted, so iterating over a PriorityQueue does not return the elements in priority order; only repeated poll calls do.
How do you make a PriorityQueue return the largest element first?
Show answer
Pass a comparator that reverses the order: new PriorityQueue<>(Comparator.reverseOrder()). For objects, pass a comparator on the field that sets the priority, for example Comparator.comparingInt(Task::getPriority).reversed().
Key Points to Remember
- Queue models FIFO processing with two parallel method families: exception-throwing and value-returning.
- PriorityQueue always retrieves the smallest element next (by Comparable or Comparator), not insertion order, in O(log n).
- ArrayDeque gives O(1) operations at both ends and is the recommended modern replacement for Stack.
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering