The PriorityQueue
in Java is a powerful implementation of the Queue
interface that orders elements by priority rather than insertion order. Internally, it uses a binary min-heap, ensuring that the smallest (or highest-priority) element is always at the front.
In this tutorial, you'll learn how Java's PriorityQueue
works, what makes it different from other queues, when to use it, and how to integrate it into modern Java applications.
🧠 What is PriorityQueue in Java?
- A heap-based priority queue that doesn’t guarantee FIFO behavior
- By default, acts as a min-heap (lowest element has the highest priority)
- Allows custom ordering via
Comparator
- Part of
java.util
and implementsQueue
Queue<Integer> pq = new PriorityQueue<>();
pq.offer(10);
pq.offer(2);
pq.offer(8);
System.out.println(pq.poll()); // 2 (min value)
⚙️ Internal Structure: Binary Min-Heap
- Implemented as a binary heap inside an array (Object[])
- Maintains heap invariant: for every parent node, value <= children
- New elements added to end, then “heapify up”
- Polling removes root, last element replaces root, “heapify down”
// Internal array example: [2, 5, 3, 9]
// Heap property maintained: parent ≤ children
Default Capacity:
- Initial capacity = 11
- Grows dynamically with resizing (
Arrays.copyOf
)
📦 Syntax and Method Overview
Method | Description |
---|---|
offer(E e) |
Inserts element respecting heap property |
poll() |
Retrieves and removes head (min element) |
peek() |
Retrieves head without removing |
remove(E e) |
Removes a specific element |
comparator() |
Returns custom comparator or null |
PriorityQueue<String> pq = new PriorityQueue<>();
pq.add("Banana");
pq.add("Apple");
pq.add("Mango");
System.out.println(pq.poll()); // Apple (lexicographically smallest)
🔄 Custom Ordering with Comparator
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
maxHeap.add(10);
maxHeap.add(2);
System.out.println(maxHeap.poll()); // 10 (max value first)
⏱️ Performance Benchmarks
Operation | Time Complexity |
---|---|
offer() |
O(log n) |
poll() |
O(log n) |
peek() |
O(1) |
remove() |
O(n) |
iterator() |
O(n) (unsorted) |
PriorityQueue is not sorted when iterated.
✅ Real-World Use Cases
- Task scheduling with priorities
- Shortest-path algorithms (e.g., Dijkstra)
- Bandwidth throttling
- Job dispatchers
- Rate-limiting logic
class Task {
int priority;
String name;
}
PriorityQueue<Task> tasks = new PriorityQueue<>(Comparator.comparingInt(t -> t.priority));
🔁 PriorityQueue vs Queue vs TreeSet
Feature | PriorityQueue | Queue (LinkedList) | TreeSet |
---|---|---|---|
Ordering | By priority | FIFO | Sorted + Unique |
Null Support | ❌ (no nulls) | ✅ (allows nulls) | ❌ (NPE risk) |
Performance | O(log n) | O(1) for head ops | O(log n) |
Duplicate Support | ✅ Yes | ✅ Yes | ❌ No |
🧬 Functional Java Example
List<Integer> nums = List.of(7, 2, 5, 1);
PriorityQueue<Integer> pq = nums.stream()
.collect(Collectors.toCollection(PriorityQueue::new));
System.out.println(pq.poll()); // 1
❌ Common Mistakes and Anti-Patterns
- ❌ Assuming FIFO behavior — PriorityQueue is not FIFO
- ❌ Relying on iteration order — it's not sorted during iteration
- ❌ Adding null — will throw
NullPointerException
- ❌ Using non-comparable objects without a comparator
✅ Always provide a comparator if elements do not implement Comparable
.
📌 What's New in Java Versions?
Java 8
- Lambdas + streams work with PriorityQueue
- Functional comparator support
Java 9
- Factory methods for immutable collections
Java 10
var
for cleaner type inference
Java 11–17
- Performance improvements to heap allocations
Java 21
- Structured concurrency enhances task prioritization via heap-based schedulers
🔧 Refactoring Legacy Code
Before:
Collections.sort(list);
return list.get(0); // slow
After (PriorityQueue):
PriorityQueue<Integer> pq = new PriorityQueue<>(list);
return pq.peek(); // fast
🧠 Real-World Analogy
Think of a hospital emergency room. Patients with higher priority (lower value) get treated first — not those who arrived first. That’s exactly how a
PriorityQueue
works.
❓ FAQ – Expert-Level Questions
-
Can I store null in a PriorityQueue?
- No. It will throw
NullPointerException
.
- No. It will throw
-
Is PriorityQueue thread-safe?
- No. Use
PriorityBlockingQueue
for concurrent access.
- No. Use
-
Does PriorityQueue maintain sorting?
- No. Only the head is guaranteed to be the highest priority.
-
Can I convert PriorityQueue to a sorted list?
List<Integer> sorted = new ArrayList<>(pq); Collections.sort(sorted);
-
What's the difference between min-heap and max-heap?
- Min-heap gives smallest first; max-heap gives largest (use reverse comparator).
-
What happens if I add non-comparable objects?
- Throws
ClassCastException
unless comparator is provided.
- Throws
-
What if two elements have same priority?
- Tie-breaker is insertion order (heap behavior).
-
How do I remove a specific element?
- Use
pq.remove(Object o)
, O(n) complexity.
- Use
-
Can I use PriorityQueue with custom classes?
- Yes, override
compareTo()
or useComparator
.
- Yes, override
-
What's the initial capacity of PriorityQueue?
- 11 elements. Grows automatically as needed.
🏁 Conclusion and Key Takeaways
- Java's
PriorityQueue
offers an efficient min-heap implementation - Useful for ordered processing, but not suitable for FIFO needs
- Internally backed by a binary heap
- Always be mindful of iteration behavior and type comparability
- Leverage
Comparator.comparing()
for clean, functional designs
🚀 Pro Tip: For queue + order, use
PriorityQueue
. For queue + concurrency, usePriorityBlockingQueue
.