PriorityQueue
Data Structures
Programming
Java
Coding Tutorial

How do I use a PriorityQueue?

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

A PriorityQueue is useful when the next item you want is the best one according to some priority rule, not the oldest one inserted. In Java, PriorityQueue is usually backed by a binary heap, which makes it efficient for repeated insertion and repeated removal of the top-priority element.

Default Behavior Is a Min-Heap

Java's PriorityQueue returns the smallest element first when you store values with their natural ordering.

java
1import java.util.PriorityQueue;
2
3public class Main {
4    public static void main(String[] args) {
5        PriorityQueue<Integer> pq = new PriorityQueue<>();
6
7        pq.offer(40);
8        pq.offer(10);
9        pq.offer(25);
10        pq.offer(5);
11
12        System.out.println("Head: " + pq.peek());
13
14        while (!pq.isEmpty()) {
15            System.out.println(pq.poll());
16        }
17    }
18}

The important operations are:

  • 'offer or add to insert'
  • 'peek to inspect the current head'
  • 'poll to remove the current head'

The queue is ordered for these head operations, not for arbitrary iteration.

Use a Comparator for Max-Heap Behavior

If you want the largest element first, pass a comparator.

java
1import java.util.Comparator;
2import java.util.PriorityQueue;
3
4public class Main {
5    public static void main(String[] args) {
6        PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());
7
8        pq.offer(40);
9        pq.offer(10);
10        pq.offer(25);
11        pq.offer(5);
12
13        while (!pq.isEmpty()) {
14            System.out.println(pq.poll());
15        }
16    }
17}

This changes the priority rule but not the rest of the API.

Store Custom Objects with an Explicit Ordering

A PriorityQueue becomes most useful when the elements are domain objects such as tasks, events, or graph nodes. In that case, give the queue a comparator based on the field that represents priority.

java
1import java.util.Comparator;
2import java.util.PriorityQueue;
3
4class Task {
5    final String name;
6    final int priority;
7
8    Task(String name, int priority) {
9        this.name = name;
10        this.priority = priority;
11    }
12}
13
14public class Main {
15    public static void main(String[] args) {
16        PriorityQueue<Task> pq = new PriorityQueue<>(Comparator.comparingInt(task -> task.priority));
17
18        pq.offer(new Task("write report", 3));
19        pq.offer(new Task("fix outage", 1));
20        pq.offer(new Task("reply to email", 5));
21
22        while (!pq.isEmpty()) {
23            Task task = pq.poll();
24            System.out.println(task.name + " -> " + task.priority);
25        }
26    }
27}

Here the smallest numeric priority comes out first. If your domain treats larger numbers as more urgent, reverse the comparator.

Do Not Expect Sorted Iteration

One of the most common surprises is that printing or iterating over a PriorityQueue does not show fully sorted order.

java
System.out.println(pq);

That output reflects the internal heap layout, not a sorted list. The sorting guarantee applies only to the head element returned by peek or poll.

If you need the full contents in priority order, remove them repeatedly with poll, or copy them into another structure and sort separately.

Complexity and Typical Use Cases

The main performance properties are:

  • insertion: O(log n)
  • removal of head: O(log n)
  • inspection of head: O(1)

That makes PriorityQueue a good fit for:

  • task scheduling
  • simulation event queues
  • Dijkstra and A-star style algorithms
  • merging streams by timestamp or score

It is not the right tool when you need frequent random removal of arbitrary elements or stable FIFO ordering among equal priorities.

Mutating an Element After Insertion

If you change the priority field of an object after it is already inside the queue, the heap does not automatically reorder itself.

The safe pattern is:

  • remove and reinsert the element
  • or insert an updated copy and ignore stale entries later

This matters in graph algorithms and schedulers where priorities change over time.

offer Versus add

In practice, offer and add both insert into a normal unbounded PriorityQueue. Many developers prefer offer because it matches the queue vocabulary and fits better if you later work with bounded queues where offer and add differ more clearly.

For a standard Java PriorityQueue, either is fine.

Common Pitfalls

A common mistake is assuming Java's PriorityQueue is a max-heap by default. It is not.

Another mistake is printing the queue and expecting sorted output. Only head operations are guaranteed by priority.

Developers also sometimes mutate an element's priority after insertion and assume the queue will fix itself automatically. It will not.

Finally, be careful with comparators. Write them explicitly and clearly instead of relying on risky arithmetic shortcuts.

Summary

  • Java PriorityQueue gives fast access to the next element by priority.
  • By default it is a min-heap.
  • Use a comparator for max-heap behavior or custom object ordering.
  • Trust peek and poll, not iteration order.
  • Reinsert elements if their priority changes after they are already in the queue.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.