Table of Contents
PriorityBlockingQueue in Java
The PriorityBlockingQueue is a class in Java that implements the BlockingQueue interface and extends the AbstractQueue class. It implements the concurrent BlockingQueue data structure. The working of a PriorityBlockingQueue is similar to a PriorityQueue but enforces a blocking retrieval operation. This means when we try to add elements when there is no resource, it will throw OutOfMemoryError. Similarly, we cannot remove elements when the queue is empty.
Features
- We cannot store null values in a PriorityBlockingQueue.
- It is unbounded and grows dynamically with an initial capacity of 11.
- There is no guarantee that we can retrieve elements in a particular order using the iterator() or spliterator() methods.
- To sort the elements we can either use the Arrays.sort or use custom classes or comparators.
- The elements that we add in a PriorityBlockingQueue need to implement a Comparable interface else it will throw ClassCastException.
- PriorityBlockingQueue in Java is thread-safe.
- We can use the drainTo() method to remove the priority elements and store them in another collection.
Hierarchy
Constructors of PriorityBlockingQueue in Java
Constructor | Description |
---|---|
PriorityBlockingQueue() | Creates a default empty PriorityBlockingQueue with capacity 11 |
PriorityBlockingQueue(Collection c) | Creates a PriorityBlockingQueue with the specified elements in the collection |
PriorityBlockingQueue(int initialCapacity) | Creates an empty PriorityBlockingQueue with the specified initial capacity |
PriorityBlockingQueue(int initialCapacity, Comparator c) | Creates an empty PriorityBlockingQueue with the specified initial capacity and orders the elements based on the comparator |
Methods of PriorityBlockingQueue in Java
Method | Description | Parameter |
---|---|---|
Boolean add(String e) | Adds the specified element to the end of the queue | e - the element to be added. Return value - True |
Boolean addAll(Collection c) | Adds a collection of specified elements to the queue. | c - collection of elements to be added Return value - true |
void clear() | Clears all the elements in the queue. | |
Comparator comparator() | Returns the comparator to order the elements | |
Boolean contains(Object o) | Checks if the queue contains the specified element | Return value - true if the queue contains the element |
Boolean containsAll(Collection c) | Checks if the queue contains all the elements in the collection | Return value - true if the queue contains all the elements |
int drainTo(Collection c) | Removes all the elements from the queue and adds it to the specified collection | c - Collection to which elements needs to be added |
int drainTo(Collection c, int maxElements) | Removes the specified maximum number of elements from the queue and adds to the specified collection | c - Collection to which elements needs to be added maxElements - Maximum number of elements that can be transferred |
Integer element() | Returns the first element(head) in the queue | |
Boolean equals(Object o) | Compares if the queue contains all the specified elements in the exact order | Return value - true if object elements match with the queue |
Boolean isEmpty() | Checks if the queue is empty or not | Return value - true if queue contains no values |
Iterator iterator() | Retrieves the iterator of queue in sequence | Return value - Iterator |
Boolean offer(Integer e) | Inserts the specified element as the tail | e - element to be added |
Boolean offer(Integer e, long timeout, TimeUnit unit) | Inserts the specified element to the queue | e - element to be added |
Integer peek() | Retrieves the first element of the queue(head) | Returns null if the queue is empty |
Integer poll() | Retrieves and removes the first element of the queue(head) | Returns null if the queue is empty |
Integer poll(long timeout, TimeUnit unit) | Retrieves and removes the head element from the queue by waiting for the specified time if the element is unavailable | timeout - waiting time |
void put(Integer e) | Inserts the specified element to the queue | e - element to be inserted |
int remainingCapacity() | Returns the Integer.MAX_VALUE | |
Integer remove() | Removes the first element from the queue | |
Boolean remove(Object o) | Removes the first occurrence of the specified object from the queue if present | o - The element that needs to be removed Return value - true if queue contains the element |
Boolean removeAll(Collection c) | Removes the first occurrence of all the elements in the collection from the queue if present | c - collection of elements Return value - true if the queue contains the collection |
Boolean retainAll(Collection c) | Retains all the elements specified in collection in queue. Other elements will be removed | c - collection of elements that has to be retained Return value - true if the queue changed due to the method called |
int size() | Fetches the size of the queue | Return value - size of the queue |
Spliterator spliterator() | Returns a spliterator over the elements in the queue | |
Integer take() | Retrieves and removes the head of the queue | |
Object[] toArray() | Returns an array of elements in proper sequence | Return value - Array of all elements in the queue in proper sequence |
String toString() | Returns a String representation of the elements collection | Return value - String of array elements separated by comma and space and enclosed within [] |
Example: Add elements to PriorityBlockingQueue
The below example shows how to add elements to a PriorityBlockingQueue in Java. We can insert values using the add(), offer() or put() method whereas to insert a collection of values, we can use the addAll() method.
import java.util.concurrent.PriorityBlockingQueue; public class AddElementsPriorityBlockingQueue { public static void main(String[] args) { PriorityBlockingQueue<Integer> pb = new PriorityBlockingQueue<Integer>(); pb.add(30); pb.add(50); pb.add(10); System.out.println("Elements in PriorityBlockingQueue after add: " + pb); PriorityBlockingQueue<Integer> pbq = new PriorityBlockingQueue<Integer>(); pbq.add(70); pbq.add(90); pb.addAll(pbq); System.out.println("Elements in PriorityBlockingQueue after addAll: " + pb); pb.put(100); System.out.println("Elements in PriorityBlockingQueue after put: " + pb); pb.offer(110); System.out.println("Elements in PriorityBlockingQueue after offer: " + pb); } }
Elements in PriorityBlockingQueue after add: [10, 50, 30] Elements in PriorityBlockingQueue after addAll: [10, 50, 30, 70, 90] Elements in PriorityBlockingQueue after put: [10, 50, 30, 70, 90, 100] Elements in PriorityBlockingQueue after offer: [10, 50, 30, 70, 90, 100, 110]
Example: Remove elements from PriorityBlockingQueue
In the below example, we show how to delete elements using the remove() method. We can also remove the head element using the poll() method. To retain only the collection of elements and delete other elements, we can use the retainAll() method whereas to remove all the collection elements, we can use the removeAll() method.
import java.util.concurrent.PriorityBlockingQueue; public class DeleteElementsPriorityBlockingQueue throws InterruptedException { public static void main(String[] args) { PriorityBlockingQueue<Integer> pb = new PriorityBlockingQueue<Integer>(); pb.add(30); pb.add(50); pb.add(10); PriorityBlockingQueue<Integer> pbq = new PriorityBlockingQueue<Integer>(); pbq.add(70); pbq.add(90); pbq.add(100); pb.addAll(pbq); System.out.println("Elements in PriorityBlockingQueue after add: " + pb); pb.remove(); pb.remove(90); System.out.println("Elements in PriorityBlockingQueue after remove: " + pb); Integer val = pb.poll(); System.out.println("Removed element using poll: " + val); Integer value = pb.take(); System.out.println("Removed element using take: " + value); pb.retainAll(pbq); System.out.println("Elements in PriorityBlockingQueue after retainAll: " + pb); pb.removeAll(pbq); System.out.println("Elements in PriorityBlockingQueue after removeAll: " + pb); } }
Elements in PriorityBlockingQueue after add: [10, 50, 30, 70, 90, 100] Elements in PriorityBlockingQueue after remove: [30, 50, 100, 70] Removed element using poll: 30 Removed element using take: 50 Elements in PriorityBlockingQueue after retainAll: [70, 100] Elements in PriorityBlockingQueue after removeAll: []
Example: Access elements in PriorityBlockingQueue
To check if a particular value exists in the PriorityBlockingQueue, we can use the contains() method whereas to check the existence of a collection of elements, we can use the containsAll() method. In the below example, we can see how to retrieve the head element using the element() and peek() methods.
import java.util.concurrent.PriorityBlockingQueue; public class AccessElementsPBQ { public static void main(String[] args) { PriorityBlockingQueue<Integer> pb = new PriorityBlockingQueue<Integer>(); pb.add(30); pb.add(50); pb.add(10); pb.add(20); pb.add(40); PriorityBlockingQueue<Integer> pbq = new PriorityBlockingQueue<Integer>(); pbq.add(70); pbq.add(90); pb.addAll(pbq); System.out.println(pb.contains(100)); System.out.println(pb.contains(20)); System.out.println(pb.containsAll(pbq)); System.out.println("Head element using the element() method: " + pb.element()); System.out.println("Head element using the peek method: " + pb.peek()); } }
false true true Head element using the element() method: 10 Head element using the peek method: 10
Example: Iterate over PriorityBlockingQueue
We can traverse through all values in a PriorityBlockingQueue in Java using the iterator() method.
import java.util.Iterator; import java.util.concurrent.PriorityBlockingQueue; public class IteratePBQ { public static void main(String[] args) { PriorityBlockingQueue<Integer> pb = new PriorityBlockingQueue<Integer>(); pb.add(30); pb.add(50); pb.add(10); pb.add(20); pb.add(40); //Using iterator System.out.println("Using iterator:"); Iterator<Integer> i = pb.iterator(); while(i.hasNext()) System.out.println(i.next()); } }
Using iterator: 10 20 30 50 40
Example: drainTo() method
Below is an example of how to remove elements from one collection and transfer them to another collection using the drainTo() method. We can notice that the first queue pb is empty after using the drainTo() method and the second queue pbq is filled with values of pb.
import java.util.concurrent.PriorityBlockingQueue; public class drainToDemo { public static void main(String[] args) { PriorityBlockingQueue<Integer> pb = new PriorityBlockingQueue<Integer>(); pb.add(30); pb.add(50); pb.add(10); pb.add(20); pb.add(40); PriorityBlockingQueue<Integer> pbq = new PriorityBlockingQueue<Integer>(); pb.drainTo(pbq); System.out.println("Elements in the first collection: " + pb); System.out.println("Elements in the second collection: " + pbq); } }
Elements in the first collection: [] Elements in the second collection: [10, 20, 30, 40, 50]
Example: Using comparator in PriorityBlockingQueue
We can order the elements in the PriorityQueue based on a custom comparator. In the below example, we create a custom comparator that returns the highest element as the head.
import java.util.Comparator; import java.util.concurrent.PriorityBlockingQueue; public class ComparatorPBQ { public static void main(String[] args) { PriorityBlockingQueue<Integer> pb = new PriorityBlockingQueue<Integer>(5, new SampleComparator()); pb.add(30); pb.add(50); pb.add(10); pb.add(20); pb.add(40); System.out.println(pb); } }
Comparator.java
import java.util.Comparator; public class SampleComparator implements Comparator<Integer> { @Override public int compare(Integer x, Integer y) { if(x < y) return 1; else return -1; } }
[50, 40, 10, 20, 30]
Example: Blocking retrieval operation
Below is an example to demonstrate the blocking retrieval operation using the PriorityBlockingQueue. When a new thread starts, it waits for a second before printing every integer value. The take() method, retrieves and removes the element by waiting for the value for the specified time.
import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.TimeUnit; public class BlockingRetrievalDemo { public static void main(String[] args) throws InterruptedException { PriorityBlockingQueue<Integer> pb = new PriorityBlockingQueue<Integer>(); new Thread(() -> { System.out.println("Waiting..."); try { while(true) { Integer t = pb.take(); System.out.println("Value: " + t); Thread.sleep(TimeUnit.SECONDS.toMillis(1)); } } catch(Exception e) { e.printStackTrace(); } } ).start(); Thread.sleep(TimeUnit.SECONDS.toMillis(2)); pb.add(10); Thread.sleep(TimeUnit.SECONDS.toMillis(2)); pb.add(20); Thread.sleep(TimeUnit.SECONDS.toMillis(2)); pb.add(30); } }
Waiting... Value: 10 Value: 20 Value: 30
Example: Creating a PriorityBlockingQueue from a Collection
The below example shows how to create a PriorityBlockingQueue from a LinkedList Collection. We can see that there is a difference in the order it lists the values in a LinkedList and PriorityBlockingQueue.
import java.util.LinkedList; import java.util.concurrent.PriorityBlockingQueue; public class PBQCollection { public static void main(String[] args) { LinkedList<Integer> l = new LinkedList<Integer>(); l.add(10); l.add(80); l.add(40); l.add(20); l.add(30); System.out.println("Elements in LinkedList: " + l); PriorityBlockingQueue<Integer> p = new PriorityBlockingQueue<Integer>(l); System.out.println("Elements in PriorityBlockingQueue: " + p); } }
Elements in LinkedList: [10, 80, 40, 20, 30] Elements in PriorityBlockingQueue: [10, 20, 40, 80, 30]
Example: Sorting using Inbuilt comparator
We can sort the values in a PriorityBlockingQueue in Java using the built-in comparator. In the below example, we print the values in the reverse order using the Comparator built-in method reverseOrder().
import java.util.Comparator; import java.util.concurrent.PriorityBlockingQueue; public class ComparatorPBQDemo { public static void main(String[] args) { PriorityBlockingQueue<Integer> pbq = new PriorityBlockingQueue<Integer>(5, Comparator.reverseOrder()); pbq.add(20); pbq.add(40); pbq.add(60); pbq.add(80); pbq.add(100); System.out.println(pbq); } }
[100, 80, 40, 20, 60]