Java PriorityQueue && PriorityBlockingQueue

Java PriorityQueue && PriorityBlockingQueuejava

咱們知道隊列是遵循先進先出(First-In-First-Out)模式的,但有些時候須要在隊列中基於優先級處理對象。舉個例子,比方說咱們有一個每日交易時段生成股票報告的應用程序,須要處理大量數據而且花費不少處理時間。客戶向這個應用程序發送請求時,實際上就進入了隊列。咱們須要首先處理優先客戶再處理普通用戶。在這種狀況下,Java的PriorityQueue(優先隊列)會頗有幫助。安全

PriorityQueue類在Java1.5中引入並做爲 Java Collections Framework 的一部分。PriorityQueue是基於優先堆的一個無界隊列,這個優先隊列中的元素能夠默認天然排序或者經過提供的Comparator(比較器)在隊列實例化的時排序。多線程

優先隊列不容許空值,並且不支持non-comparable(不可比較)的對象,好比用戶自定義的類。優先隊列要求使用Java Comparable和Comparator接口給對象排序,而且在排序時會按照優先級處理其中的元素。dom

優先隊列的頭是基於天然排序或者Comparator排序的最小元素。若是有多個對象擁有一樣的排序,那麼就可能隨機地取其中任意一個。當咱們獲取隊列時,返回隊列的頭對象。ide

優先隊列的大小是不受限制的,但在建立時能夠指定初始大小。當咱們向優先隊列增長元素的時候,隊列大小會自動增長。測試

PriorityQueue是非線程安全的,因此Java提供了PriorityBlockingQueue(實現BlockingQueue接口)用於Java多線程環境。this

咱們有一個用戶類Customer,它沒有提供任何類型的排序。當咱們用它創建優先隊列時,應該爲其提供一個比較器對象。spa

Customer.java線程

package com.journaldev.collections;
 
public class Customer {
 
    private int id;
    private String name;
 
    public Customer(int i, String n){
        this.id=i;
        this.name=n;
    }
 
    public int getId() {
        return id;
    }
 
    public String getName() {
        return name;
    }
 
}

咱們使用Java隨機數生成隨機用戶對象。對於天然排序,咱們使用Integer對象,這也是一個封裝過的Java對象。下面是最終的測試代碼,展現如何使用PriorityQueue:code

PriorityQueueExample.java

package com.journaldev.collections;
 
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
 
public class PriorityQueueExample {
 
    public static void main(String[] args) {
 
        //優先隊列天然排序示例
        Queue<Integer> integerPriorityQueue = new PriorityQueue<>(7);
        Random rand = new Random();
        for(int i=0;i<7;i++){
            integerPriorityQueue.add(new Integer(rand.nextInt(100)));
        }
        for(int i=0;i<7;i++){
            Integer in = integerPriorityQueue.poll();
            System.out.println("Processing Integer:"+in);
        }
 
        //優先隊列使用示例
        Queue<Customer> customerPriorityQueue = new PriorityQueue<>(7, idComparator);
        addDataToQueue(customerPriorityQueue);
 
        pollDataFromQueue(customerPriorityQueue);
 
    }
 
    //匿名Comparator實現
    public static Comparator<Customer> idComparator = new Comparator<Customer>(){
 
        @Override
        public int compare(Customer c1, Customer c2) {
            return (int) (c1.getId() - c2.getId());
        }
    };
 
    //用於往隊列增長數據的通用方法
    private static void addDataToQueue(Queue<Customer> customerPriorityQueue) {
        Random rand = new Random();
        for(int i=0; i<7; i++){
            int id = rand.nextInt(100);
            customerPriorityQueue.add(new Customer(id, "Pankaj "+id));
        }
    }
 
    //用於從隊列取數據的通用方法
    private static void pollDataFromQueue(Queue<Customer> customerPriorityQueue) {
        while(true){
            Customer cust = customerPriorityQueue.poll();
            if(cust == null) break;
            System.out.println("Processing Customer with ID="+cust.getId());
        }
    }
 
}

 

注意我用實現了Comparator接口的Java匿名類,而且實現了基於id的比較器。

當我運行以上測試程序時,我獲得如下輸出:

Processing Integer:9
Processing Integer:16
Processing Integer:18
Processing Integer:25
Processing Integer:33
Processing Integer:75
Processing Integer:77
Processing Customer with ID=6
Processing Customer with ID=20
Processing Customer with ID=24
Processing Customer with ID=28
Processing Customer with ID=29
Processing Customer with ID=82
Processing Customer with ID=96

 

從輸出結果能夠清楚的看到,最小的元素在隊列的頭部於是最早被取出。若是不實現Comparator,在創建customerPriorityQueue時會拋出ClassCastException。

Exception in thread "main" java.lang.ClassCastException: com.journaldev.collections.Customer cannot be cast to java.lang.Comparable
    at java.util.PriorityQueue.siftUpComparable(PriorityQueue.java:633)
    at java.util.PriorityQueue.siftUp(PriorityQueue.java:629)
    at java.util.PriorityQueue.offer(PriorityQueue.java:329)
    at java.util.PriorityQueue.add(PriorityQueue.java:306)
    at com.journaldev.collections.PriorityQueueExample.addDataToQueue(PriorityQueueExample.java:45)
    at com.journaldev.collections.PriorityQueueExample.main(PriorityQueueExample.java:25)

==========END==========

相關文章
相關標籤/搜索