Java Priority Queue (PriorityQueue) Example

We know that Queue follows First-In-First-Out model but sometimes we need to process the objects in the queue based on the priority. For example, let’s say we have an application that generates stocks reports for daily trading session and it processes a lot of data and takes time to process it. So customers are sending request to the application that is actually getting queued but we want to process premium customers first and standard customers after them. So in this casePriorityQueue implementation in java can be really helpful.
PriorityQueue class was introduced in Java 1.5 and part of Java Collections Framework. PriorityQueue is an unbounded queue based on a priority heap and the elements of the priority queue are ordered by default in natural order or we can provide a Comparator for ordering at the time of instantiation of queue.
PriorityQueue doesn’t allow null values and we can’t create PriorityQueue of Objects that are non-comparable, for example any custom classes we have. We use java Comparable and Comparator interfaces for sorting Objects and PriorityQueue use them for priority processing of it’s elements.
The head of the priority queue is the least element based on the natural ordering or comparator based ordering, if there are multiple objects with same ordering, then it can poll any one of them randomly. When we poll the queue, it returns the head object from the queue.
PriorityQueue size is unbounded but we can specify the initial capacity at the time of it’s creation. When we add elements to the priority queue, it’s capacity grows automatically.
PriorityQueue is not thread safe, so java provides PriorityBlockingQueue class that implements the BlockingQueue interface to use injava multi-threading environment.
PriorityQueue implementation provides O(log(n)) time for enqueing and dequeing method. Let’s see an example of PriorityQueue for natural ordering as well as with Comparator.
We have our custom class Customer that doesn’t provide any type of ordering, so when we will try to use it with PriorityQueue we should provide a comparator object for that.
01package com.journaldev.collections;
02
03public class Customer {
04
05    private int id;
06    private String name;
07
08    public Customer(int i, String n){
09        this.id=i;
10        this.name=n;
11    }
12
13    public int getId() {
14        return id;
15    }
16
17    public String getName() {
18        return name;
19    }
20
21}
We will use java random number generation to generate random customer objects. For natural ordering, I will use Integer that is also ajava wrapper class.
Here is our final test code that shows how to use PriorityQueue.
01package com.journaldev.collections;
02
03import java.util.Comparator;
04import java.util.PriorityQueue;
05import java.util.Queue;
06import java.util.Random;
07
08public class PriorityQueueExample {
09
10    public static void main(String[] args) {
11
12        //natural ordering example of priority queue
13        Queue<Integer> integerPriorityQueue = new PriorityQueue<>(7);
14        Random rand = new Random();
15        for(int i=0;i<7;i++){
16            integerPriorityQueue.add(new Integer(rand.nextInt(100)));
17        }
18        for(int i=0;i<7;i++){
19            Integer in = integerPriorityQueue.poll();
20            System.out.println("Processing Integer:"+in);
21        }
22
23        //PriorityQueue example with Comparator
24        Queue<Customer> customerPriorityQueue = new PriorityQueue<>(7, idComparator);
25        addDataToQueue(customerPriorityQueue);
26
27        pollDataFromQueue(customerPriorityQueue);
28
29    }
30
31    //Comparator anonymous class implementation
32    public static Comparator<Customer> idComparator = new Comparator<Customer>(){
33
34        @Override
35        public int compare(Customer c1, Customer c2) {
36            return (int) (c1.getId() - c2.getId());
37        }
38    };
39
40    //utility method to add random data to Queue
41    private static void addDataToQueue(Queue<Customer> customerPriorityQueue) {
42        Random rand = new Random();
43        for(int i=0; i<7; i++){
44            int id = rand.nextInt(100);
45            customerPriorityQueue.add(new Customer(id, "Customer- "+id));
46        }
47    }
48
49    //utility method to poll data from queue
50    private static void pollDataFromQueue(Queue<Customer> customerPriorityQueue) {
51        while(true){
52            Customer cust = customerPriorityQueue.poll();
53            if(cust == nullbreak;
54            System.out.println("Processing Customer with ID="+cust.getId());
55        }
56    }
57
58}
Notice that I am using java anonymous class for implementing Comparator interface and creating our id based comparator.
When I run above test program, I get following output:
01Processing Integer:9
02Processing Integer:16
03Processing Integer:18
04Processing Integer:25
05Processing Integer:33
06Processing Integer:75
07Processing Integer:77
08Processing Customer with ID=6
09Processing Customer with ID=20
10Processing Customer with ID=24
11Processing Customer with ID=28
12Processing Customer with ID=29
13Processing Customer with ID=82
14Processing Customer with ID=96
From output it’s clear that least element was at head and got polled first. If we won’t provide comparator while creatingcustomerPriorityQueue, it will throw ClassCastException at runtime.
1Exception in thread "main" java.lang.ClassCastException: com.journaldev.collections.Customer cannot be cast to java.lang.Comparable
2    at java.util.PriorityQueue.siftUpComparable(PriorityQueue.java:633)
3    at java.util.PriorityQueue.siftUp(PriorityQueue.java:629)
4    at java.util.PriorityQueue.offer(PriorityQueue.java:329)
5    at java.util.PriorityQueue.add(PriorityQueue.java:306)
6    at com.journaldev.collections.PriorityQueueExample.addDataToQueue(PriorityQueueExample.java:45)
7    at com.journaldev.collections.PriorityQueueExample.main(PriorityQueueExample.java:25)

No comments :

Post a Comment