本文由 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; |
3 |
public class Customer
{ |
8 |
public Customer( int i,
String n){ |
17 |
public String
getName() { |
我們使用Java隨機數生成隨機使用者物件。對於自然排序,我們使用Integer物件,這也是一個封裝過的Java物件。
下面是最終的測試程式碼,展示如何使用PriorityQueue:
PriorityQueueExample.java
1 |
package com.journaldev.collections; |
3 |
import java.util.Comparator; |
4 |
import java.util.PriorityQueue; |
5 |
import java.util.Queue; |
6 |
import java.util.Random; |
8 |
public class PriorityQueueExample
{ |
10 |
public static void main(String[]
args) { |
13 |
Queue<Integer>
integerPriorityQueue = new PriorityQueue<>( 7 ); |
14 |
Random
rand = new Random(); |
16 |
integerPriorityQueue.add( new Integer(rand.nextInt( 100 ))); |
19 |
Integer
in = integerPriorityQueue.poll(); |
20 |
System.out.println( "Processing
Integer:" +in); |
24 |
Queue<Customer>
customerPriorityQueue = new PriorityQueue<>( 7 ,
idComparator); |
25 |
addDataToQueue(customerPriorityQueue); |
27 |
pollDataFromQueue(customerPriorityQueue); |
32 |
public static Comparator<Customer>
idComparator = new Comparator<Customer>(){ |
35 |
public int compare(Customer
c1, Customer c2) { |
36 |
return ( int )
(c1.getId() - c2.getId()); |
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)); |
50 |
private static void pollDataFromQueue(Queue<Customer>
customerPriorityQueue) { |
52 |
Customer
cust = customerPriorityQueue.poll(); |
53 |
if (cust
== null ) break ; |
54 |
System.out.println( "Processing
Customer with ID=" +cust.getId()); |
注意我用實現了Comparator介面的Java匿名類,並且實現了基於id的比較器。
當我執行以上測試程式時,我得到以下輸出:
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
[
轉載請保留原文出處、譯者、譯文連結和上面的微信二維碼圖片。]
相關文章