Article written by Shashi Kadapa, under the guidance of Neeraj Jhawar, a Senior Software Development Manager and Engineering Leader. Reviewed by Manish Chawla, a problem-solver, ML enthusiast, and an Engineering Leader with 20+ years of experience.
PriorityQueue in Java is a min-heap by default, the element with the lowest value is always at the head of the queue. Unlike a regular queue that processes elements in insertion order, PriorityQueue processes them by priority. It is backed internally by a binary heap, which gives it O(log n) insert and remove operations. To use it as a max-heap or sort by a custom field, you need a Comparator.
This article covers every constructor, all key methods with time complexity, how to set up min and max heaps, custom Comparator patterns, the iteration gotcha that trips up candidates in interviews, and the most common interview problem patterns where PriorityQueue is the right tool.
PriorityQueue in Java is a queue where elements are retrieved in priority order rather than insertion order. It is backed by a binary min-heap internally, meaning the element with the smallest value according to natural ordering is always at the head. Every insertion and removal restructures the heap to maintain this property. PriorityQueue is part of java.util and implements the Queue interface. It allows duplicate elements but does not permit null values.
PriorityQueue extends AbstractQueue, which implements Queue, which extends Collection, which extends Iterable. The full hierarchy is: Iterable → Collection → Queue → AbstractQueue → PriorityQueue.
Java provides four main constructors for PriorityQueue. The Comparator constructor is the most important one for interview use, as it is how you switch between min-heap and max-heap behavior.
| Constructor | Syntax | Use Case |
| Default | new PriorityQueue<>() | Creates a min-heap with default initial capacity of 11. Uses natural ordering. |
| With initial capacity | new PriorityQueue<>(int initialCapacity) | Creates a min-heap with a specified initial capacity. Useful when you know the approximate size upfront. |
| With Comparator | new PriorityQueue<>(Comparator<E> comparator) | Creates a PriorityQueue with custom ordering. Use Collections.reverseOrder() for a max-heap. |
| With capacity and Comparator | new PriorityQueue<>(int initialCapacity, Comparator<E> comparator) | Combines custom capacity and custom ordering. Most flexible constructor. |
Example: Creating PriorityQueues with different constructors
// Default min-heap PriorityQueue<Integer> minHeap = new PriorityQueue<>(); // Min-heap with initial capacity PriorityQueue<Integer> pq = new PriorityQueue<>(20); // Max-heap using Collections.reverseOrder() PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder()); // Max-heap with initial capacity PriorityQueue<Integer> maxHeap2 = new PriorityQueue<>(20, Collections.reverseOrder());
Java PriorityQueue provides the following key methods. All structural modifications, adding and removing elements trigger heap restructuring, which is why insert and poll operations are O(log n).
| Method | Description | Time Complexity | Returns |
| add(E e) | Inserts an element. Throws IllegalStateException if capacity is exceeded (bounded queues only). | O(log n) | true |
| offer(E e) | Inserts an element. Returns false if capacity is exceeded instead of throwing. For unbounded queues (default), identical to add(). | O(log n) | true / false |
| poll() | Removes and returns the head element (lowest priority). Returns null if queue is empty. | O(log n) | Head element or null |
| peek() | Returns the head element without removing it. Returns null if queue is empty. | O(1) | Head element or null |
| remove(Object o) | Removes a specific element by value. Requires a linear scan of the backing array. | O(n) | true / false |
| contains(Object o) | Returns true if the queue contains the specified element. | O(n) | true / false |
| size() | Returns the number of elements currently in the queue. | O(1) | int |
| clear() | Removes all elements from the queue. | O(n) | void |
| toArray() | Returns all elements as an Object array. Order is NOT guaranteed to be priority order. | O(n) | Object[] |
Join 25,000+ tech professionals who’ve accelerated their careers with cutting-edge AI skills
For the default unbounded PriorityQueue, add() and offer() behave identically, both insert the element and return true. The distinction applies only to bounded queues: add() throws an IllegalStateException when the queue has reached capacity, while offer() returns false instead. Since Java’s standard PriorityQueue is unbounded (it grows dynamically), this distinction rarely matters in practice but is a frequent interview question.
poll() removes the head element from the queue and returns it. If the queue is empty, it returns null. peek() returns the head element without removing it, also returning null if empty. Use peek() when you need to inspect the top element without modifying the queue, for example, when comparing the top of two heaps without advancing either.
Java PriorityQueue is a min-heap by default. The element with the smallest value according to natural ordering is always at the head. When you call poll(), it removes and returns the smallest element first. For integers, this means 1 comes out before 5 before 10. For strings, natural ordering is lexicographic. This default behavior is the source of the most common PriorityQueue interview mistake, using a default PriorityQueue when a max-heap is needed, or vice versa.
Pass Collections.reverseOrder() as the Comparator when constructing the PriorityQueue. This reverses the natural ordering so the largest element sits at the head instead of the smallest.
Max-heap using Collections.reverseOrder()
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder()); maxHeap.add(3); maxHeap.add(10); maxHeap.add(7); System.out.println(maxHeap.poll()); // Output: 10 System.out.println(maxHeap.poll()); // Output: 7 System.out.println(maxHeap.poll()); // Output: 3
For non-primitive types or when sorting by a specific field, pass a lambda or Comparator implementation to the PriorityQueue constructor. This is the most interview-relevant usage; interval scheduling, task scheduling, and object sorting problems all require custom Comparators.
Custom Comparator – sort int[] arrays by second element (common in interval problems)
// Sort int[] arrays by second element (end time in interval problems) PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[1] - b[1]); // Sort by object field — example: Person sorted by age ascending PriorityQueue<Person> byAge = new PriorityQueue<>((a, b) -> a.age - b.age); // Sort by object field descending PriorityQueue<Person> byAgeDesc = new PriorityQueue<>((a, b) -> b.age - a.age);
Common PriorityQueue Comparator patterns used in interview problems:
| Use Case | Comparator Code | Notes |
| Max-heap (integers) | Collections.reverseOrder() | Standard approach. Reverses natural integer ordering. |
| Max-heap (lambda) | (a, b) -> b – a | Lambda equivalent of reverseOrder for integers. |
| Sort by object field ascending | (a, b) -> a.field – b.field | Works for numeric fields. Use Comparator.comparingInt for safety. |
| Sort by object field descending | (a, b) -> b.field – a.field | Reverses the field comparison. |
| Sort by array element | (a, b) -> a[i] – b[i] | Extremely common in interval and scheduling problems. Replace i with the index you need. |
Every structural operation, adding and removing elements, triggers heap restructuring (sifting up or sifting down), which is why those operations are O(log n). contains() and remove(Object) require a linear scan of the internal backing array, making them O(n). This is why using PriorityQueue for membership checks is inefficient, use a HashSet alongside if you need fast lookups.
| Operation | Time Complexity | Why |
| add() / offer() | O(log n) | Element is added at the end and sifted up to restore heap order. Heap height is log n. |
| poll() / remove() | O(log n) | Head is removed, last element moves to head, then sifts down. Heap height is log n. |
| peek() | O(1) | Head element is always at index 0 of the backing array. Direct access. |
| contains() | O(n) | No index structure – requires a full linear scan of the backing array. |
| remove(Object) | O(n) | Same as contains: linear scan to find the element, then O(log n) to restructure. |
| size() | O(1) | Stored as a field. No computation required. |
| Space complexity | O(n) | The backing array stores all n elements. |
No. Iterating a PriorityQueue with a for-each loop or iterator does NOT return elements in priority order. It returns elements in the internal heap array order, which is undefined from the caller’s perspective. This surprises most candidates the first time they see it, and it is a common interview gotcha. To process elements in priority order, use poll() in a loop.
CORRECT – Process in priority order using poll()
PriorityQueue<Integer> pq = new PriorityQueue<>(); pq.add(5); pq.add(1); pq.add(3); // CORRECT: poll() processes in ascending order while (!pq.isEmpty()) { System.out.println(pq.poll()); // prints: 1, 3, 5 }
WRONG – for-each loop does NOT return elements in priority order
// WRONG: for-each does NOT guarantee priority order for (int x : pq) { System.out.println(x); // undefined order — do NOT use this }
Join 25,000+ tech professionals who’ve accelerated their careers with cutting-edge AI skills
PriorityQueue is the go-to data structure for a specific family of interview problems. Understanding which pattern maps to which heap type is the skill that separates candidates who solve these correctly from those who get the approach right but the implementation wrong. See also: heap data structure guide.
| Pattern | PriorityQueue Role | Example Problems |
| Kth Largest / Kth Smallest | Use a min-heap of size K to find Kth largest, or a max-heap of size K to find Kth smallest. The heap head gives the answer in O(1) after processing all elements. | Kth Largest Element in an Array (LC 215), K Closest Points to Origin (LC 973) |
| Merge K Sorted Lists | Use a min-heap to always extract the globally smallest element across K lists. Push the next element from the same list after each extraction. | Merge K Sorted Lists (LC 23), Smallest Range Covering Elements from K Lists (LC 632) |
| Top K Frequent Elements | Use a min-heap of size K keyed on frequency. After processing all elements, the heap contains the K most frequent. | Top K Frequent Elements (LC 347), Top K Frequent Words (LC 692) |
| Task Scheduling | Use a max-heap to always process the most frequent remaining task first. Combine with a cooldown queue. | Task Scheduler (LC 621), Reorganize String (LC 767) |
| Dijkstra’s Algorithm | Use a min-heap keyed on distance to always process the nearest unvisited node first. Core to shortest path problems. | Network Delay Time (LC 743), Cheapest Flights Within K Stops (LC 787) |
| Meeting Rooms / Intervals | Use a min-heap of end times to efficiently track which meetings have ended before the next one starts. | Meeting Rooms II (LC 253), Car Pooling (LC 1094) |
Interview Pattern Rule: Kth Largest problems always use a min-heap of size K, not a max-heap. The logic: keep only the K largest elements seen so far. If a new element beats the current minimum (heap head), swap it in. After processing all elements, the heap head is the Kth largest. Getting the heap type wrong here, reaching for a max-heap instead, is one of the most common interview mistakes on heap problems.
Java’s PriorityQueue gives you a min-heap by default with O(log n) insert and poll. The real interview skill is not knowing the API; it is knowing when to use a min-heap versus a max-heap and recognizing which pattern a problem belongs to before you write a single line of code. Most heap problems at FAANG companies involve one of five patterns: Kth element, merge K sorted, top K frequent, shortest path, or interval scheduling. Getting fluent with those patterns and the corresponding heap setup is what converts PriorityQueue knowledge into correct interview solutions.
No. PriorityQueue does not permit null elements. Inserting null throws a NullPointerException immediately. This is different from some other Java collections like LinkedList or ArrayDeque that allow null. If you need a priority queue that can hold null, you need a custom implementation.
No. PriorityQueue is not thread-safe. If multiple threads access the same PriorityQueue concurrently and at least one modifies it, external synchronization is required. For concurrent use cases, use PriorityBlockingQueue from java.util.concurrent, which provides the same priority ordering with built-in thread safety.
The default initial capacity of PriorityQueue in Java is 11. The queue grows automatically as elements are added, capacity roughly doubles when the backing array runs out of space. You rarely need to set this manually unless you are optimizing for a very large known dataset size.
PriorityQueue allows duplicate elements and provides O(log n) access only to the minimum element (or maximum with a custom Comparator). TreeSet does not allow duplicates and provides O(log n) access to any element including min, max, floor, and ceiling. Use PriorityQueue when you need repeated access to the minimum or maximum element and duplicates are expected. Use TreeSet when you need a sorted set with range operations and duplicates are not allowed.
Recommended Reads:
By sharing your contact details, you agree to our privacy policy.
Time Zone: Asia/Dhaka
Give us more details about yourself so that our FAANG Experts can suggest the best options for you!
Master ML interviews with DSA, ML System Design, Supervised/Unsupervised Learning, DL, and FAANG-level interview prep.
Get strategies to ace TPM interviews with training in program planning, execution, reporting, and behavioral frameworks.
Course covering SQL, ETL pipelines, data modeling, scalable systems, and FAANG interview prep to land top DE roles.
Course covering Embedded C, microcontrollers, system design, and debugging to crack FAANG-level Embedded SWE interviews.
Nail FAANG+ Engineering Management interviews with focused training for leadership, Scalable System Design, and coding.
End-to-end prep program to master FAANG-level SQL, statistics, ML, A/B testing, DL, and FAANG-level DS interviews.
Learn to build AI agents to automate your repetitive workflows
Upskill yourself with AI and Machine learning skills
Prepare for the toughest interviews with FAANG+ mentorship
Time Zone:
Join 25,000+ tech professionals who’ve accelerated their careers with cutting-edge AI skills
25,000+ Professionals Trained
₹23 LPA Average Hike 60% Average Hike
600+ MAANG+ Instructors
Webinar Slot Blocked
Register for our webinar
Learn about hiring processes, interview strategies. Find the best course for you.
ⓘ Used to send reminder for webinar
Time Zone: Asia/Kolkata
Time Zone: Asia/Kolkata
Hands-on AI/ML learning + interview prep to help you win
Explore your personalized path to AI/ML/Gen AI success
The 11 Neural “Power Patterns” For Solving Any FAANG Interview Problem 12.5X Faster Than 99.8% OF Applicants
The 2 “Magic Questions” That Reveal Whether You’re Good Enough To Receive A Lucrative Big Tech Offer
The “Instant Income Multiplier” That 2-3X’s Your Current Tech Salary
Join 25,000+ tech professionals who’ve accelerated their careers with cutting-edge AI skills
Join 25,000+ tech professionals who’ve accelerated their careers with cutting-edge AI skills
Webinar Slot Blocked
Time Zone: Asia/Kolkata
Hands-on AI/ML learning + interview prep to help you win
Time Zone: Asia/Kolkata
Hands-on AI/ML learning + interview prep to help you win
Explore your personalized path to AI/ML/Gen AI success
See you there!