Java优先队列(PriorityQueue)示例

我们知道队列是遵循先进先出(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
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:

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)

<figure style="margin: 1em 0px;">
image

</figure>

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home...
    光剑书架上的书阅读 4,204评论 2 8
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 35,026评论 18 399
  • 别人怎么看你不重要,唯一重要的是你很喜欢真实的自己。 不要在最美好的年华里辜负自己,你自己的努力你自己可以看得见,...
    P尐c阅读 420评论 2 2
  • Sheldon办公室出现一个美女,所有人都来围观,期待被介绍。没想到她就是Sheldon的孪生妹妹Missy。大家...
    fries看美剧学英语阅读 13,342评论 0 0
  • 从周一开始了每天的一次的晨读,5点钟早起是个难关,很多有名的,自己崇拜的人物都是早起。给自己早起要做的事做个仪式,...
    赵翰林阅读 328评论 0 0

友情链接更多精彩内容