DevNotes
Support
Collection Framework · Chapter 13

PriorityQueue

Priority-ordered processing on a binary min-heap — sift-up, sift-down, max-heaps, custom priorities and Top-K patterns.

◷ 12 min read§ 20 sections? 15 interview questions{ } 24 code examples

#Introduction

PriorityQueue is one of the most important Queue implementations for interviews because it introduces a completely different concept:

The head is determined by priority, not insertion order.

Internally, PriorityQueue uses a binary heap, specifically a min-heap by default.

#What is PriorityQueue?

Package:

Java
java.util.PriorityQueue

Declaration:

Java
public class PriorityQueue<E>
        extends AbstractQueue<E>
        implements Serializable

Key characteristics:

  • Allows duplicate elements
  • Does not allow null
  • Not thread-safe
  • Default ordering is natural ordering
  • Custom ordering can be supplied using a Comparator
  • The head contains the highest-priority element
  • Default priority = smallest element
  • Internally uses a binary heap

#PriorityQueue Is Not FIFO

This is the first thing to remember. A normal Queue with 10 → 20 → 30 returns 10 from poll() because it was inserted first. A PriorityQueue:

Java
Queue<Integer> queue = new PriorityQueue<>();

queue.offer(30);
queue.offer(10);
queue.offer(20);

The head is 10 because 10 has the highest priority under natural ordering. So insertion order ≠ processing order.

Default Priority

For numbers, the smallest number has the highest priority.

Java
PriorityQueue<Integer> pq = new PriorityQueue<>();

pq.offer(50);
pq.offer(10);
pq.offer(30);
pq.offer(20);

Repeated poll():

Output
10
20
30
50

This behaves like a min-priority queue.

#Internal Structure — Binary Heap

PriorityQueue is backed by an array representing a complete binary tree.

  • 10
    • 20
      • 50
      • 40
    • 30
Min-heap property: Parent <= Children, so the smallest element is always at the root

Array Representation

The tree above is represented in an array as:

[0]
10
[1]
20
[2]
30
[3]
50
[4]
40

This is why PriorityQueue doesn't need separate Node objects like LinkedList.

Why a Complete Binary Tree?

A heap must be a complete binary tree:

  • Every level is completely filled except possibly the last.
  • The last level is filled from left to right.

This makes the tree compact and efficiently representable using an array.

Parent/Child Index Formula

For an element at index i:

RelationFormula
Parent(i - 1) / 2
Left child2 * i + 1
Right child2 * i + 2

Example: index 0 → left = 1, right = 2. Index 1 → parent = 0, left = 3, right = 4. These formulas are frequently asked in coding interviews.

#offer() and Sift-Up

Java
pq.offer(5);
New element
Place at end of heap
Compare with parent
Parent larger?
Swap and continue upward
Done
This is called Sift Up (or Bubble Up)

Sift-Up Example

Heap is 10 → (20, 30). Insert 5:

Initially
10children: 20, 30
20child: 5
After first swap
10children: 5, 30
5child: 20
Heap restored
5children: 10, 30
10child: 20

Complexity of offer()

The new element may move from the bottom to the root. Heap height is O(log n), therefore offer() → O(log n).

#peek()

Java
pq.peek();

The smallest element is always at the root (array index 0). Therefore peek() → O(1). No restructuring is necessary.

#poll() and Sift-Down

This is one of the most important PriorityQueue questions.

  • 10
    • 20
      • 40
      • 50
    • 30
Heap before poll()

poll() removes 10. The last element (50) is moved to the root:

  • 50
    • 20
      • 40
    • 30
Heap property is now violated

Java performs sift down: swap with the smaller child until the heap property is restored.

50 at rootchildren 20, 30
20 at root50 now has child 40
Heap restored20 → (40, 30), 40 → (50)

Therefore poll() → O(log n).

#Complexity Table

OperationComplexity
peek()O(1)
offer() / add()O(log n)
poll() / remove()O(log n) — head removal
contains()O(n)
remove(Object)O(n)
size()O(1)

The key operations: peek → O(1), offer → O(log n), poll → O(log n).

#Iteration Is Not Sorted

Important Trap

Java
PriorityQueue<Integer> pq = new PriorityQueue<>();

pq.offer(30);
pq.offer(10);
pq.offer(20);
pq.offer(5);

Don't assume this prints 5, 10, 20, 30:

Java
for (Integer x : pq) {
    System.out.println(x);
}

It is not guaranteed to iterate in sorted order. The heap guarantees the correct head, not sorted iteration.

How to Get Elements in Priority Order

Use repeated poll():

Java
while (!pq.isEmpty()) {
    System.out.println(pq.poll());
}
Output
5
10
20
30

PriorityQueue vs Sorted Collection

Don't confuse PriorityQueue with TreeSet. PriorityQueue guarantees the highest-priority element at the head; it does not maintain all elements in globally sorted iteration order. TreeSet maintains sorted ordering of its elements.

#PriorityQueue vs TreeSet

FeaturePriorityQueueTreeSet
DuplicatesAllowedNot allowed
OrderingHead priorityEntire set sorted
Internal structureBinary heapRed-Black Tree
peek() / first()O(1)O(log n) typically
InsertO(log n)O(log n)
Remove head/minO(log n)O(log n)
Random accessNoNo
NullNoGenerally no

Use PriorityQueue when you mainly care about repeatedly processing the next highest-priority item.

#Custom Priority

Reverse Order — Max-Heap

By default the smallest element has the highest priority, but you can reverse it:

Java
PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());

Now repeated poll() returns 50, 40, 30, 20, 10 — the largest number has the highest priority. This effectively creates a max-priority queue.

Java
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());

maxHeap.offer(10);
maxHeap.offer(50);
maxHeap.offer(20);

System.out.println(maxHeap.poll());
Output
50

Custom Objects

Java
class Task {
    int priority;
    String name;

    Task(int priority, String name) {
        this.priority = priority;
        this.name = name;
    }
}
Java
PriorityQueue<Task> tasks = new PriorityQueue<>(Comparator.comparingInt(t -> t.priority));

tasks.offer(new Task(3, "Email"));
tasks.offer(new Task(1, "Payment"));
tasks.offer(new Task(2, "Report"));

Processing order (assuming a smaller priority number means higher priority):

Output
Payment
Report
Email

Multiple Sorting Conditions

A very common interview requirement: order by priority, and if the priority is the same, by timestamp.

Java
PriorityQueue<Task> queue = new PriorityQueue<>(
        Comparator
                .comparingInt((Task t) -> t.priority)
                .thenComparing(t -> t.timestamp)
);

This allows sophisticated scheduling policies.

#Duplicates, Null and Capacity

Duplicates

Unlike Set, PriorityQueue allows duplicates:

Java
pq.offer(10);
pq.offer(10);
pq.offer(10);

All three elements remain. This is an important difference from TreeSet.

Null Elements

PriorityQueue does not permit null:

Java
pq.offer(null);
Output
NullPointerException

Why? The queue needs to compare elements according to natural ordering or the supplied Comparator, and null does not have a natural ordering by itself.

Initial Capacity

Java
PriorityQueue<Integer> pq = new PriorityQueue<>(100);

This controls the initial backing-array capacity. It does not mean 100 elements are inserted — it's simply storage capacity.

Does PriorityQueue Grow?

Yes. It uses a dynamically growing array. When the backing array becomes full: current array → grow → copy elements → continue. The exact growth strategy is implementation-specific — don't apply ArrayList's growth formula here.

#Thread Safety

PriorityQueue Is Not Thread-Safe

Java
PriorityQueue<Integer> pq = new PriorityQueue<>();

is not thread-safe. If multiple threads need concurrent priority-queue behaviour, Java provides PriorityBlockingQueue from java.util.concurrent.

PriorityBlockingQueue

Java
BlockingQueue<Task> queue = new PriorityBlockingQueue<>();

It combines priority ordering + BlockingQueue semantics.

#Real-World Use Cases

Use caseHow PriorityQueue helps
Task schedulingCritical tasks → high priority → normal tasks
Hospital / support ticketsEmergency → High → Medium → Low: process the most important item first
Dijkstra's algorithmRepeatedly select the node with the smallest tentative distance
A* searchSelect the node with the smallest estimated total cost
Top-K problemsK largest, K smallest, top K frequent, K closest points

#Top-K Problems

Extremely important for coding interviews.

Top-K Largest Example

Input 10, 40, 20, 50, 30; need the top 3 largest. A common strategy is to maintain a min-heap of size K:

  • Process elements one by one.
  • If the new element is larger than the smallest heap element: remove the smallest, insert the new element.
  • At the end, the heap contains the top 3 candidates.

Complexity: O(n log k) — much better than sorting all n elements when k is small.

Why a Min-Heap for Top-K Largest?

Suppose K = 3 and we currently keep 50, 40, 30. The smallest among our current top 3 is 30. If 45 arrives: 45 > 30, so remove 30 and insert 45 → now 50, 45, 40.

The root always represents the weakest member of the current Top-K set, which makes replacement efficient.

Coding Pattern — K Largest Elements

Java
PriorityQueue<Integer> minHeap = new PriorityQueue<>();

for (int n : numbers) {
    minHeap.offer(n);
    if (minHeap.size() > k) {
        minHeap.poll();
    }
}

// minHeap now contains the K largest elements

Complexity O(n log k), space O(k). This is an extremely useful pattern to remember.

Coding Pattern — K Smallest Elements

Use a max-heap of size K. The largest among the current K smallest elements stays at the root. If a smaller value arrives, remove the largest and insert the smaller one. Complexity O(n log k) — the opposite of the Top-K Largest pattern.

#PriorityQueue vs ArrayDeque vs LinkedList

PriorityQueue vs ArrayDeque

FeaturePriorityQueueArrayDeque
OrderingPriorityFIFO / deque order
Internal structureBinary heapResizable array/deque
peek() returnsHighest priorityFront
offer()O(log n)O(1) amortized
poll()O(log n)O(1)
DuplicatesYesYes
NullNoNo

PriorityQueue vs LinkedList

FeaturePriorityQueueLinkedList
Normal FIFO❌ No✅ Yes
Priority ordering✅ Yes❌ No
StructureHeapDoubly linked list
peek()O(1)O(1)
poll()O(log n)O(1)
DuplicatesYesYes
Null❌ No✅ Yes

Choose based on ordering requirements.

#Common Interview Traps

ClaimVerdict
"PriorityQueue maintains all elements in sorted order."❌ No — only the head is guaranteed to have the highest priority.
"PriorityQueue follows FIFO."❌ No — it follows its priority ordering.
"peek() is O(log n)."❌ No — the root is directly available: O(1).
"poll() is O(1)."❌ No — after removing the root, heap restructuring may be necessary: O(log n).
"PriorityQueue doesn't allow duplicates."❌ Wrong — duplicates are allowed.
"PriorityQueue is thread-safe."❌ Wrong — use PriorityBlockingQueue for concurrent/blocking use cases.

#Frequently Asked Interview Questions

Q1What is PriorityQueue?

A Queue implementation that processes elements according to priority rather than normal FIFO insertion order.

Q2What data structure does PriorityQueue use internally?

A binary heap stored in an array.

Q3What is the default heap?

Min-heap. The smallest element has the highest priority.

Q4What is the complexity of peek()?

O(1).

Q5What is the complexity of offer()?

O(log n).

Q6What is the complexity of poll()?

O(log n).

Q7Does PriorityQueue allow duplicates?

Yes.

Q8Does PriorityQueue allow null?

No.

Q9How do you create a max-heap?
Java
PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());
Q10Does iterating over PriorityQueue produce sorted output?

No. Use repeated poll() if you need elements processed in priority order.

Q11What is a heap?

A complete binary tree satisfying a heap-order property.

Q12Why is PriorityQueue efficient?

The heap keeps the highest-priority element at the root while maintaining O(log n) insertion and removal.

Q13What is PriorityBlockingQueue?

A concurrent, blocking-capable priority queue implementation.

Q14Quick test: what is the output?
Java
PriorityQueue<Integer> pq = new PriorityQueue<>();

pq.offer(40);
pq.offer(10);
pq.offer(30);
pq.offer(20);

System.out.println(pq.peek());
System.out.println(pq.poll());
System.out.println(pq.poll());
Output
10
10
20
Q15Tricky question: can you guarantee System.out.println(pq) prints [10, 20, 30]?
Java
PriorityQueue<Integer> pq = new PriorityQueue<>();

pq.add(30);
pq.add(10);
pq.add(20);

System.out.println(pq);

No. The toString() / iterator view does not guarantee sorted order. If you need priority order:

Java
while (!pq.isEmpty()) {
    System.out.println(pq.poll());
}

#Decision Framework

Need a Queue?
Need FIFO?
ArrayDeque
PriorityQueue
Priority + concurrencyPriorityBlockingQueue

Final Mental Model

PriorityQueue
Binary Heap
Array Storage
Operation
O(1) — root element
O(log n) — remove root, sift down
O(log n) — add at end, sift up

The three operations to memorize: peek() → O(1), offer() → O(log n), poll() → O(log n).

#Chapter Summary

ConceptPriorityQueue
TypeQueue
OrderingPriority
Default prioritySmallest element
Internal structureBinary heap
Heap typeMin-heap by default
StorageResizable array
peek()O(1)
offer()O(log n)
poll()O(log n)
DuplicatesAllowed
NullNot allowed
Thread-safeNo
Max-heapComparator.reverseOrder()
Sorted iterationNo
Priority processingYes
Concurrent alternativePriorityBlockingQueue

Interview Readiness Checklist

  • Why PriorityQueue is not FIFO
  • What a binary heap is
  • Min-heap vs max-heap
  • How offer() works
  • What sift-up means
  • How poll() works
  • What sift-down means
  • Why peek() is O(1)
  • Why poll() is O(log n)
  • Why iteration isn't sorted
  • How to create a max-heap
  • How duplicates behave
  • Why null isn't allowed
  • PriorityQueue vs TreeSet
  • PriorityQueue vs ArrayDeque
  • How PriorityQueue solves Top-K problems
  • What PriorityBlockingQueue is