Priority Queues
A PriorityQueue can sort a collection: add all items with addAll, then remove them one at a time until the queue is empty.
Try it: Stack and Queue
The difference between a stack (last in, first out) and a queue (first in, first out).
How it works
- A stack adds (push) and removes (pop) at the same end, the top — the last item added leaves first.
- A queue adds (enqueue) at the back and removes (dequeue) from the front — the first item added leaves first.
- peek / front look at the next item without removing it.
- Adding to a full structure is an overflow; removing from an empty one is an underflow.
Default run (3 steps): Stack (bottom → top): 4, 7. 2 of 8 slots used. Choose an operation. Example: push 9. … Stack is now: 4, 7, 9. Size 3/8.
Simplified: Fixed capacity of 8 items so overflow can be shown; Python lists and collections.deque grow as needed.
Loading the simulation…
A Second Route to Sorted Output
Earlier in the course you saw that a TreeSet can sort the items in a collection and remove duplicates along the way. A PriorityQueue offers a second route to sorted output. Instead of asking a set to keep its items ordered, you place every item into a priority queue and then take the items back out one at a time. The questions this article answers are simple: what order do the items come out in, and what happens to duplicates when you do this?
The technique has two stages. In the first stage, every item is added to the queue. In the second stage, items are removed one at a time inside a loop until the queue is empty. The sorting does not come from the queue handing you a finished list. It comes from the rule that governs each removal, and the rest of this article builds up that rule step by step.
What a Priority Queue Actually Promises
A priority queue is an abstract data type that represents a collection of items. Each item has an assigned priority, which allows any two items to be compared. Its remove operation returns the item with the minimum priority currently present in the queue, not the item that arrived first.
Many learners quietly assume that a priority queue is just an ordinary queue, where the item added first leaves first and the item added last waits its turn. That assumption feels natural because the word queue suggests a line of people. A priority queue follows a different rule. Position in the line does not decide which item comes out. The priority does.
The Three Essential Operations
The Java PriorityQueue class is written as a parameterized class, PriorityQueue<T>, which implements a priority queue of objects of type T. The class also implements the Collection<T> interface, so a priority queue object has every method that interface defines. The operations essential to a priority queue, however, are only three: add, remove, and isEmpty.
- 1add places an item into the queue. During the sorting technique, this is the first stage, where
addAllputs every item in the collection into the queue. - 2
isEmptyreports whether the queue currently holds any items. It is the check that controls the draining loop. - 3remove takes out and returns the item with the minimum priority currently in the queue. Each call removes one item, so the queue shrinks by one each time.
Predicting the Removal Order
Before you trace the mechanism, make a prediction. Suppose a collection holds the strings pear, apple, banana, and apple, in that order. The first stage adds all four strings to the queue. The second stage removes them one at a time until the queue is empty. Decide what the printed output will be, paying close attention to whether both copies of apple appear.
What do you think happens?
Given pear, apple, banana, and apple added in that order, what order do the four remove calls return?
Reveal answer
apple, apple, banana, pear
Strings are removed in lexicographic order, and the queue keeps duplicate items, so both copies of apple appear before banana and pear. The insertion order plays no part in the output.
apple
apple
banana
pearaddAllis the first stage: every item in coll goes into the queue.isEmptycontrols the loop, so remove is only called while items remain.- Each remove returns the item with the minimum priority still waiting, which for strings is the next item in lexicographic order.
Tracing the drain loop for pear, apple, banana, apple
Trace what each call to remove returns, and find the step where a predicted sequence that treats the queue like a plain FIFO line stops matching the real output.
- 1Stage one: addAll
All four strings enter the queue. Their insertion order is pear, apple, banana, apple, but the queue does not store them as a line to be served in that order.
- 2Remove call 1
The minimum-priority item still waiting is apple. The first copy is printed.
- 3Remove call 2
The second copy of apple is still waiting, so it is the minimum and is printed. A prediction that drops the duplicate diverges here, because the queue does not discard items.
- 4Remove call 3
banana is now the minimum and is printed.
- 5Remove call 4 and the check
pear is the last item and is printed.
isEmptynow returns true, so the loop ends.
The printed output is apple, apple, banana, pear. A plain FIFO prediction would print pear, apple, banana, apple, and it diverges at the very first line.
The diagram shows the loop as a sequence of remove calls, each followed by the isEmpty check implied by the loop. The second call is where a careless prediction usually fails. A learner who expects each distinct value to appear only once will write apple, banana, pear and stop there. The queue keeps both copies, so the second apple is printed as well.
Why Items Must Be Comparable
A remove operation that returns the minimum item only makes sense if the queue can decide, for any two items, which one is smaller. The source compares this to sorting: we need to be able to compare any two items in the queue. Without a way to make that comparison, the queue has no basis for choosing which item comes out next.
Java supports this comparison in two ways. The first is to have the item's class implement the Comparable interface and its compareTo() method. The second is to supply a Comparator to the PriorityQueue constructor. Both ways mirror the two standard approaches to sorting objects, and both give the queue the decision it needs.
The source names String, Integer, and Date as classes that implement Comparable. Objects of these classes can be used directly in a priority queue, which is what makes the sorting technique work without extra setup. The practical rule follows: if the elements you want to sort belong to a class that implements Comparable, you can add them to a PriorityQueue and remove them to get sorted output. The source does not describe how to sort elements of a class that does not implement Comparable, so this article makes no claim about that case.
Comparing a Priority Queue With a Plain Queue
Consider the same insertion sequence fed into two structures. A plain first-in, first-out queue returns items in the order they were added, so pear, apple, banana comes out as pear, apple, banana. A priority queue given the same insertion sequence returns the minimum-priority item at each step. For strings, that produces lexicographic order, so the output becomes apple, banana, pear.
The two columns in the figure hold the same three values, but the removal order differs. The FIFO column follows arrival order, while the priority queue column follows priority. This difference is the core idea of the whole article: a priority queue is not a line that serves people in turn.
Sorting With a PriorityQueue Versus a TreeSet
The source presents the PriorityQueue technique as a companion to the TreeSet technique. Both can sort a collection, but they differ on duplicates. A TreeSet removes duplicates as it sorts. The PriorityQueue technique keeps duplicate items in the output. Comparing the two on the same input makes this difference easy to see.
| Question | PriorityQueue technique | TreeSet technique |
|---|---|---|
| How items are sorted | Added with addAll, then removed one at a time | Kept in order by the set as items are added |
| Duplicates in the input | Kept in the output | Removed along the way |
| Output for pear, apple, banana, apple | apple, apple, banana, pear | apple, banana, pear |
| Ordering supplied by | Comparable or a Comparator | Comparable or a Comparator |
The duplicate behavior is the key difference between the two sorting techniques.
The figure makes the difference concrete. The priority queue holds and outputs four items, including both copies of apple. The TreeSet outputs three, because the duplicate apple is removed. If your goal is a sorted list that preserves every item, the priority queue technique matches that goal. If your goal is a sorted list of distinct values, the TreeSet is the better fit.
Two Implementation Strategies and Their Costs
The source describes two broad ways to implement a priority queue. The simplest uses a linked list that keeps items in order of increasing priority. In that design, remove is simple, because it removes and returns the first item in the list. Add is the expensive part, because the new item must be inserted into its correct position. The average run time for add in this design is Theta(n), where n is the number of items in the list.
The source also states that priority queues can be implemented so that both add and remove have run time Theta(log(n)), which is much more efficient. That efficient version uses a heap. The source does not explain how a heap arranges its items and says it will not discuss that implementation in the section, so this article does not describe the arrangement. What you can rely on is the complexity contrast between the two designs.
| Implementation | Cost of add | Cost of remove |
|---|---|---|
| Linked list kept in priority order | Theta(n) on average | Simple removal of the first item |
| Heap-based implementation | Theta(log(n)) | Theta(log(n)) |
Both designs support the same removal rule. They differ in how much work add and remove cost.
Two Meanings of the Word Heap
The word heap appears in this topic in a specific sense. A heap is the data structure that an efficient priority queue implementation uses. It is distinct from the other memory the word is often used for, which is the area where objects are created while a program runs. A learner should keep these apart. The heap data structure is an internal technique for keeping a priority queue's ordering efficient. The objects stored in the queue are separate items that the queue refers to.
Common Mistakes With Priority Queues
Common mistake Predicting that a priority queue returns items in insertion order
What it looks likeAdding pear, apple, banana and expecting pear to come out first.
Why it failsThe remove operation returns the item with the minimum priority among those waiting, not the item that arrived first.
Do this insteadFor strings, expect lexicographic order: apple, banana, pear.
Common mistake Dropping the second copy of a duplicate value
What it looks likePredicting apple, banana, pear for the input pear, apple, banana, apple.
Why it failsA
PriorityQueuekeeps duplicate items, unlike aTreeSet, so both copies of apple are removed.Do this insteadPredict apple, apple, banana, pear and count the removals.
Common mistake Calling remove on an empty queue
Why it failsIn Java, remove throws an exception when the queue is empty.
Do this insteadGuard the loop with isEmpty, so that remove runs only while items remain.
Common mistake Adding objects with no way to compare them
Why it failsThe queue must decide which of two items is smaller, and it cannot do that without a comparison.
Do this insteadUse a class that implements Comparable, or supply a Comparator to the PriorityQueue constructor.
Practice: Predict Before You Check
A collection holds the strings kiwi, cherry, kiwi, apple, in that order. Using the add-all-then-remove-until-empty technique, write down the exact sequence of strings the loop prints. Then state whether the output contains kiwi once or twice, and explain why.
Hints
- Ask first what the removal rule says about which item comes out on each remove call.
- Count the copies of kiwi in the input before you count them in your predicted output.
- Compare your predicted list with what the
TreeSettechnique would print, and note the difference in duplicates.
Key Takeaways
- A
PriorityQueuesorts a collection by usingaddAllto add every item and then calling remove, inside a loop guarded byisEmpty, until the queue is empty. - A priority queue's remove returns the item with the minimum priority currently present, which is not the same as a first-in, first-out queue.
- For strings, Integer, and Date, which implement Comparable, the queue output is in order, and duplicates are kept in the output, unlike a
TreeSet. - Items must be comparable, through the Comparable interface and
compareTo(), or through a Comparator supplied to thePriorityQueueconstructor. - A linked-list design makes add expensive at Theta(n) on average, while a heap-based design achieves Theta(log(n)) for both add and remove.