The PriorityQueue Class
Objective
Understand PriorityQueue, the Queue implementation that orders its elements by a comparator (or natural ordering) instead of insertion order — the head is always the smallest element by that ordering, backed internally by a heap rather than a fully-sorted structure.
Use Cases
- Scheduling work by priority — task queues, event simulation, or graph algorithms like Dijkstra's shortest path.
- Repeatedly retrieving the smallest (or, with a reversing
Comparator, the largest) element efficiently. - Streaming "top-k" computations, where only the current extreme matters, not a fully sorted list.
- Plugging a custom ordering into code that's written against the generic
Queueinterface.
Deep Dive
PriorityQueue extends AbstractQueue
javaclass PriorityQueue<E>Seven constructors:
javaPriorityQueue<Integer> a = new PriorityQueue<>(); // capacity 11, natural ordering
PriorityQueue<Integer> b = new PriorityQueue<>(50); // capacity 50, natural ordering
PriorityQueue<Integer> c = new PriorityQueue<>(Comparator.reverseOrder()); // max-heap via custom comparator
PriorityQueue<Integer> d = new PriorityQueue<>(50, Comparator.reverseOrder()); // capacity + comparator
PriorityQueue<Integer> e = new PriorityQueue<>(List.of(3, 1, 2)); // from a CollectionCapacity grows automatically as elements are added, same as ArrayList.
Default ordering: a min-heap
Without an explicit Comparator, the natural ordering of the elements applies, so the smallest element is always at the head:
javaPriorityQueue<Integer> pq = new PriorityQueue<>(List.of(5, 1, 3, 2, 4));
pq.poll(); // 1 — smallest first
pq.poll(); // 2A Comparator inverts or replaces that ordering entirely — e.g. Comparator.reverseOrder() turns it into a max-heap. comparator() returns the comparator in use, or null if natural ordering applies.
Watch it happen: poll() draining in priority order
Same five elements as above, same arrival order — this shows the order repeated poll() calls hand them back, not the actual internal heap array layout (which the next section covers):
Iteration order is not priority order
javaPriorityQueue<Integer> pq = new PriorityQueue<>(List.of(5, 1, 3, 2, 4));
for (int x : pq) {
System.out.print(x + " "); // NOT guaranteed to print 1 2 3 4 5
}To retrieve elements in priority order, repeated poll() (or remove()) calls are required — the Iterator walks the underlying heap array in whatever order it's laid out in, not in priority order.
Trade-offs
A common bug: looping over the queue with a
for-each and expecting sorted output — onlypoll()/peek()respect the ordering;Iteratordoes not:javaPriorityQueue<Integer> pq = new PriorityQueue<>(List.of(3, 1, 2)); List<Integer> viaIterator = new ArrayList<>(pq); // heap order, unsorted List<Integer> viaPoll = new ArrayList<>(); while (!pq.isEmpty()) viaPoll.add(pq.poll()); // [1, 2, 3] — actually sortedoffer/poll/removeare O(log n);peek/elementare O(1) — the heap only guarantees the head is the extreme element, not that the rest of the array is sorted, which is what makes insertion/removal logarithmic instead of the O(n log n) a full sort would cost.Elements must be mutually comparable, or a
Comparatormust be supplied — as withTreeSet, a comparison failure surfaces as aClassCastExceptionat the point an ordering operation runs, not at compile time or insertion time in isolation.nullelements are rejected outright (NullPointerException), for the same reasonQueuedisallowsnullelsewhere:nulldoubles as the empty-queue sentinel forpeek()/poll().