本文由 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
[
转载请保留原文出处、译者、译文链接和上面的微信二维码图片。]
相关文章