1. 程式人生 > >安全程式設計(七)- Java優先佇列(PriorityQueue)

安全程式設計(七)- Java優先佇列(PriorityQueue)

1.引言

        我們知道佇列是遵循先進先出(First-In-First-Out)模式的,但有些時候需要在佇列中基於優先順序處理物件。舉個例子,比方說我們有一個每日交易時段生成股票報告的應用程式,需要處理大量資料並且花費很多處理時間。客戶向這個應用程式傳送請求時,實際上就進入了佇列。我們需要首先處理優先客戶再處理普通使用者。在這種情況下,Java的PriorityQueue(優先佇列)會很有幫助。

2.優先佇列的特點

        (1)PriorityQueue是基於優先堆的一個無界佇列,這個優先佇列中的元素可以預設自然排序或者通過提供的Compartor

(比較器)在佇列例項化的時排序。

        (2)優先佇列不允許空值,而且不支援non-comparable(不可比較)的物件,比如使用者自定義的類。優先佇列要求使用Java Compartable和Compartor介面給物件排序,並且在排序時會按照優先順序處理其中的元素。

        (3)優先佇列的頭是基於自然排序或者Compartor排序的最小元素。如果有多個物件擁有同樣的排序,那麼就可能隨機地取其中任意一個。當我們獲取佇列時,返回佇列的頭物件。

        (4)優先佇列的大小是不受限制的,但在建立時可以指定初始大小。當我們向優先佇列增加元素的時候,佇列大小會自動增加。

        (5)PriorityQueue是非執行緒安全的,所以Java提供了PriorityBlockingQueue(實現BlockingQueue介面)用於Java多執行緒環境

3.示例

        我們有一個使用者類Customer,它沒有提供任何型別的排序。當我們用它建立優先佇列時,應該為其提供一個比較器物件:

package cn.nuist.pers.August28;

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:

package cn.nuist.pers.August28;

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:6
Processing Integer:10
Processing Integer:29
Processing Integer:41
Processing Integer:65
Processing Integer:79
Processing Integer:98
Processing Customer with ID=10
Processing Customer with ID=20
Processing Customer with ID=27
Processing Customer with ID=65
Processing Customer with ID=91
Processing Customer with ID=94
Processing Customer with ID=96

從輸出結果可以清楚的看到,最小的元素在佇列的頭部因而最先被取出。

參考文獻:http://www.importnew.com/6932.html