In Java, PriorityQueue
is a part of the Java Collections Framework and implements a priority heap. It provides an
efficient way to handle elements that need to be processed based on their priority (defined by natural ordering or a
custom comparator). Elements are ordered by priority, where the smallest or highest-priority element is always
accessible at the head of the queue.
The PriorityQueue
is a great data structure for scenarios where elements need to be processed based on priority, such
as task scheduling, event-driven systems, or anytime you need to efficiently retrieve the smallest or largest element
repeatedly. It provides logarithmic time complexity for insertion and removal, making it efficient for maintaining order
dynamically.
However, it’s not suitable for cases where random access or ordering of all elements is needed. In those cases, other
structures like ArrayList
or TreeSet
might be more appropriate.
Advantages #
- Efficient Priority Management: The
PriorityQueue
ensures that the highest-priority element (smallest by default) is always at the head of the queue, which allows for fast retrieval of the next “most important” element. - Automatic Ordering: It automatically orders elements based on their priority, either via natural ordering or a custom comparator. This is useful in scenarios like task scheduling or handling events based on urgency.
- Flexible Ordering: You can define a custom ordering by providing a comparator when constructing the queue.
- Partial Sorting: You can efficiently access the smallest or largest element without sorting the entire collection.
Disadvantages #
- No Random Access: Unlike
ArrayList
,PriorityQueue
does not support random access to elements. You cannot directly access elements by index. - Unsorted Iterator: Iterating over a
PriorityQueue
does not return elements in sorted order. Only the head of the queue is guaranteed to be the highest-priority element. - No Null Values:
PriorityQueue
does not allownull
elements, asnull
is used as a sentinel value in queues. - Not Thread-Safe:
PriorityQueue
is not synchronized. For concurrent access, usePriorityBlockingQueue
fromjava.util.concurrent
.
Time and Space Complexity #
Operation | Time Complexity | Space Complexity | Description |
---|---|---|---|
Insertion (add/offer) | O(log n) | O(n) | Insertion takes O(log n) due to heap reordering. |
Access Minimum (peek) | O(1) | O(1) | Accessing the minimum element is constant time. |
Deletion (poll/remove) | O(log n) | O(n) | Deleting the minimum element involves heap reordering and takes O(log n). |
Search (contains) | O(n) | O(1) | Searching for an element takes linear time. |
Iteration | O(n) | O(n) | Iterating through all elements takes O(n), but the elements are not guaranteed to be in priority order. |
Space Complexity | O(n) | O(n) | The space required grows linearly with the number of elements. |
Examples #
Initialization and Adding Elements:
- Time Complexity: O(log n) for each insertion
// Initialize a PriorityQueue (min-heap by default) PriorityQueue<Integer> pq = new PriorityQueue<>(); // Add elements pq.add(5); // [5] pq.add(1); // [1, 5] (1 is the smallest, so it's at the head) pq.add(3); // [1, 5, 3] (1 is still the smallest) pq.offer(4); // [1, 4, 3, 5]
Accessing the Minimum Element (peek):
- Time Complexity: O(1)
int min = pq.peek(); // Returns 1, the smallest element (but does not remove it)
Removing the Minimum Element (poll):
- Time Complexity: O(log n)
int min = pq.poll(); // Removes and returns 1, the smallest element // Now the queue is [3, 4, 5] with 3 as the new smallest
Using a Custom Comparator:
- Time Complexity: O(log n) for adding/removing elements
// Initialize a PriorityQueue with a custom comparator (max-heap) PriorityQueue<Integer> maxPQ = new PriorityQueue<>(Comparator.reverseOrder()); maxPQ.add(5); // [5] maxPQ.add(1); // [5, 1] maxPQ.add(3); // [5, 1, 3] int max = maxPQ.peek(); // Returns 5, the largest element
Checking if an Element Exists (contains):
- Time Complexity: O(n)
boolean contains = pq.contains(3); // Returns true if the element 3 is present
Iterating Over the PriorityQueue:
- Time Complexity: O(n)
// Iterate over all elements (not in sorted order) for (Integer num : pq) { System.out.println(num); }
Handling Objects with Custom Priority (Using Comparable or Comparator):
- Time Complexity: O(log n) for insertion/removal
// Define a class that implements Comparable class Task implements Comparable<Task> { String name; int priority; Task(String name, int priority) { this.name = name; this.priority = priority; } // Compare based on priority (lower values have higher priority) @Override public int compareTo(Task other) { return Integer.compare(this.priority, other.priority); } @Override public String toString() { return name + " (priority: " + priority + ")"; } } // Initialize PriorityQueue of tasks PriorityQueue<Task> taskQueue = new PriorityQueue<>(); taskQueue.add(new Task("Task A", 3)); taskQueue.add(new Task("Task B", 1)); taskQueue.add(new Task("Task C", 2)); // Access tasks by priority Task nextTask = taskQueue.poll(); // Returns "Task B (priority: 1)"