632
技術社區[雲棲]
Java優先隊列(PriorityQueue)示例
本文由 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)
|
以上就是優先隊列的全部內容,如果你喜歡這篇文章,請參與分享或者評論。
原文鏈接: journaldev 翻譯: ImportNew.com - ImportNew讀者
譯文鏈接: https://www.importnew.com/6932.html
最後更新:2017-04-03 14:54:23