Java優先佇列(PriorityQueue)示例

青色刀客發表於2013-11-19

Java優先佇列(PriorityQueue)示例 

分享到:0


本文由 ImportNew - ImportNew讀者 翻譯自 journaldev。如需轉載本文,請先參見文章末尾處的轉載要求。

文章由@Jaskey_Lam翻譯。如果你也希望參與類似的系列文章翻譯,可以加入我們的Java開發 和 技術翻譯 小組。

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

PriorityQueue類在Java1.5中引入並作為 Java Collections Framework 的一部分。PriorityQueue是基於優先堆的一個無界佇列,這個優先佇列中的元素可以預設自然排序或者通過提供的Comparator(比較器)在佇列例項化的時排序。

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

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

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

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

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

 

Customer.java

1 package com.journaldev.collections;
2  
3 public class Customer {
4  
5     private int id;
6     private String name;
7  
8     public Customer(int i, String n){
9         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 }

我們使用Java隨機數生成隨機使用者物件。對於自然排序,我們使用Integer物件,這也是一個封裝過的Java物件

下面是最終的測試程式碼,展示如何使用PriorityQueue:

 

PriorityQueueExample.java

1 package com.journaldev.collections;
2  
3 import java.util.Comparator;
4 import java.util.PriorityQueue;
5 import java.util.Queue;
6 import java.util.Random;
7  
8 public class PriorityQueueExample {
9  
10     public static void main(String[] args) {
11  
12         //優先佇列自然排序示例
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         //優先佇列使用示例
24         Queue<Customer> customerPriorityQueue = new PriorityQueue<>(7, idComparator);
25         addDataToQueue(customerPriorityQueue);
26  
27         pollDataFromQueue(customerPriorityQueue);
28  
29     }
30  
31     //匿名Comparator實現
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     //用於往佇列增加資料的通用方法
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, "Pankaj "+id));
46         }
47     }
48  
49     //用於從佇列取資料的通用方法
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 }

注意我用實現了Comparator介面的Java匿名類,並且實現了基於id的比較器。

當我執行以上測試程式時,我得到以下輸出:

 

1 Processing Integer:9
2 Processing Integer:16
3 Processing Integer:18
4 Processing Integer:25
5 Processing Integer:33
6 Processing Integer:75
7 Processing Integer:77
8 Processing Customer with ID=6
9 Processing Customer with ID=20
10 Processing Customer with ID=24
11 Processing Customer with ID=28
12 Processing Customer with ID=29
13 Processing Customer with ID=82
14 Processing Customer with ID=96

從輸出結果可以清楚的看到,最小的元素在佇列的頭部因而最先被取出。如果不實現Comparator,在建立customerPriorityQueue時會丟擲ClassCastException。

1 Exception 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)

以上就是優先佇列的全部內容,如果你喜歡這篇文章,請參與分享或者評論。

-- 掃描加關注,微訊號: importnew --

原文連結: journaldev 翻譯:ImportNew.com ImportNew讀者
譯文連結:http://www.importnew.com/6932.html
轉載請保留原文出處、譯者、譯文連結和上面的微信二維碼圖片。]

0


相關文章

相關文章