πŸ”₯ Special Offer: Flat Discount on Your Favorite Courses! Use Coupons GET200OFF GET500OFF
β†’ Grab Offer Now ←

Working of PriorityQueue in Java  


Steps of Working of PriorityQueue:
  • Below are the steps explaining how PriorityQueue works internally in the Java Collection Framework:
    1. Creation of PriorityQueue:
      • We create a new PriorityQueue as follows:
        PriorityQueue<Integer> pq = new PriorityQueue<>();
      • A new PriorityQueue object is created internally using a min-heap (implemented via a dynamic array). Initially, it is empty and ready to store elements.
      • _____________________________
        |     |     |     |     |     |
        -----------------------------
        (Index positions of internal array)
                                
    2. Adding Elements (Insertion):
      • We add elements using the add() or offer() method:
        pq.add(30);
        pq.add(10);
        pq.add(20);
        pq.add(40);
      • When an element is inserted, it is added at the end of the array and then adjusted using the heapify-up process to maintain the min-heap property.
      • Let’s see step-by-step how the internal structure forms:
        • Step 1: Add 30 β†’ First element, becomes the root.
                    (30)
          
          Internal array:
          ______________________
          | 30 |     |     |     |
          ------------------------
          (Index: 0)
                                          
        • Step 2: Add 10 β†’ Goes to next position (index 1). Now, 10 < 30 β†’ swap occurs to maintain min-heap.
                    (10)
                    /
                  (30)
          
          Internal array:
          ______________________
          | 10 | 30 | | |
          ------------------------
          (Index: 0 1)
                                                                      
        • Step 3: Add 20 β†’ Goes to index 2. 20 > 10 β†’ Heap property valid, no swap required.
                    (10)
                    /   \
                 (30)   (20)
          
          Internal array:
          __________________________
          | 10 | 30 | 20 |     |
          --------------------------
          (Index: 0   1    2)
                                          
        • Step 4: Add 40 β†’ Goes to index 3. 40 > 30 β†’ Heap property valid, no swap required.
                    (10)
                    /   \
                 (30)   (20)
                 /
              (40)
          
          Internal array representation:
          ______________________________________
          | 10 | 30 | 20 | 40 |     |     |
          --------------------------------------
          (Index: 0   1    2    3)
                                          
    3. Retrieving Element (Using peek()):
      • The peek() method retrieves the head element of the PriorityQueue without removing it.
      • The head is always the smallest element (in natural ordering).
      • Example:
      • System.out.println(pq.peek()); // Output β†’ 10
      • Internal representation (Heap Structure):
        ______________________________________
        | 10 | 30 | 20 | 40 |    |    |
        --------------------------------------
        ↑
        Head element (smallest)
                                
      • Even though the internal array appears unsorted, the smallest element is always at the head of the queue.
    4. Removing Element (Using poll()):
      • The poll() method removes and returns the head element from the PriorityQueue.
      • After removal, the last element (40) temporarily moves to the root position, and then the heapify-down process restores order.
      • Example:
      • System.out.println(pq.poll()); // Output β†’ 10
      • Before removing (10 is head):
        ______________________________________
        | 10 | 30 | 20 | 40 |    |    |
        --------------------------------------
        ↑
        Head element (to be removed)
                                
      • After removing 10 and reordering heap:
        ______________________________________
        | 20 | 30 | 40 |    |    |    |
        --------------------------------------
        ↑
        New head (smallest after reordering)
                                
      • The PriorityQueue automatically maintains its heap structure internally after each removal.
    5. Custom Ordering (Using Comparator):
      • By default, PriorityQueue arranges elements in ascending order (min-heap).
      • You can create a max-heap using a custom comparator:
        PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a);
      • In a max-heap, the largest element has the highest priority and becomes the root:
                  (40)
                  /   \
               (30)   (20)
               /
            (10)
        
        Internal array representation:
        ______________________________________
        | 40 | 30 | 20 | 10 |     |     |
        --------------------------------------
        (Index: 0   1    2    3)
                                

PriorityQueue is Good for:
  1. Automatic element ordering:
    • PriorityQueue automatically arranges elements in their natural order (for Comparable objects) or based on a custom Comparator.
    • Ideal for problems where elements must be processed according to priority, not just insertion order.
  2. Efficient retrieval of highest/lowest priority element:
    • peek() and poll() always operate on the head element (the smallest or highest priority).
    • Useful in algorithms like Dijkstra’s shortest path, Huffman coding, and task scheduling systems.
  3. Good for dynamic data processing:
    • As new elements are inserted, the heap structure automatically adjusts using heapify-up and heapify-down operations.
    • Ensures that the most important element is always accessible at O(1) time.
  4. Flexible ordering (Min-Heap or Max-Heap):
    • By default, PriorityQueue is a Min-Heap.
    • You can create a Max-Heap using:
      PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a);
PriorityQueue is Not Good for:
  1. Random access or traversal:
    • PriorityQueue does not allow efficient random access to elements.
    • Internally backed by a heap, not an ordered list β€” so accessing arbitrary elements is O(n).
  2. Preserving insertion order:
    • Elements are ordered by priority, not by the order of insertion.
    • Not suitable when insertion order matters, e.g., for FIFO structures.
  3. Thread safety:
    • PriorityQueue is not thread-safe.
    • Use PriorityBlockingQueue for concurrent or multithreaded environments.
  4. Null elements not allowed:
    • Adding null throws a NullPointerException.
    • Because null cannot be compared with other elements.
Summary Table:
Operation Description Performance / Complexity
add(E e) / offer(E e) Inserts the specified element and maintains heap order (heapify-up). O(log n)
peek() Retrieves (but does not remove) the head element β€” the smallest or highest priority. O(1)
poll() Removes and returns the head element, then heapifies down to restore order. O(log n)
remove(Object o) Removes a specific element if present (linear search required). O(n)
contains(Object o) Checks whether the queue contains a specific element. O(n)
size() Returns the number of elements in the queue. O(1)
iterator() Returns an iterator over the elements β€” but not in any guaranteed order. O(n)
Thread Safety Not thread-safe (use PriorityBlockingQueue for concurrent use). Synchronization required externally