優先級隊列(PriprityQueue)是一種無界隊列,基於優先級堆,它的元素根據天然順序或者經過實現Comparator接口的自定義排序方式進行排序。這篇文章,咱們將建立一個Items的優先級隊列,基於價格排序,優先級隊列用來實現迪科斯徹算法(Dijkstra algorithm)很是實用。值得注意的是他的迭代器並不保證有序,若是須要按順序遍歷,最好使用Arrays.sort(pd.toArray())方法。同時它的實現不是同步的,意味着在多線程中不是線程安全的對象,能夠取而代之的是PriorityBlockingQueue,它能用於多線程環境。優先級隊列提供了O(log(n))時間在出隊和入隊的方法上,好比:offer(),poll(),add(),可是對於檢索操做如:peek(),element()提供的是常量(固定)時間。html
如何使用PriorityQueuejava
這裏是如何使用PriorityQueue的一個例子,如上所說,你可使用特定的順序來組織元素,能夠是天然順序或者元素實現Comparator接口,這個例子中,咱們把Items對象放入優先級隊列中,按照價格排序,你能夠注意下Item類的compareTo方法,它與equals方法是保持一致的,這裏把Item類做爲內部靜態類,把item存儲在優先級隊列中,你能夠一直使用poll()方法獲取價格最低的那個item。算法
package test; import java.util.PriorityQueue; import java.util.Queue; /** * Java Program to show How to use PriorityQueue in Java. This example also demonstrate * that PriorityQueue doesn't allow null elements and how PriorityQueue keeps elements i.e. ordering. * * @author */ public class PriorityQueueTest { public static void main(String args[]) { Queue<Item> items = new PriorityQueue<Item>(); items.add(new Item("IPone", 900)); items.add(new Item("IPad", 1200)); items.add(new Item("Xbox", 300)); items.add(new Item("Watch", 200)); System.out.println("Order of items in PriorityQueue"); System.out.println(items); System.out.println("Element consumed from head of the PriorityQueue : " + items.poll()); System.out.println(items); System.out.println("Element consumed from head of the PriorityQueue : " + items.poll()); System.out.println(items); System.out.println("Element consumed from head of the PriorityQueue : " + items.poll()); System.out.println(items); //items.add(null); // null elements not allowed in PriorityQueue - NullPointerException } private static class Item implements Comparable<Item> { private String name; private int price; public Item(String name, int price) { this.name = name; this.price = price; } public String getName() { return name; } public int getPrice() { return price; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Item other = (Item) obj; if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { return false; } if (this.price != other.price) { return false; } return true; } @Override public int hashCode() { int hash = 5; hash = 97 hash + (this.name != null ? this.name.hashCode() : 0); hash = 97 hash + this.price; return hash; } @Override public int compareTo(Item i) { if (this.price == i.price) { return this.name.compareTo(i.name); } return this.price - i.price; } @Override public String toString() { return String.format("%s: $%d", name, price); } } }
Output:api
Order of items in PriorityQueue [Watch: $200, Xbox: $300, IPone: $900, IPad: $1200] Element consumed from head of the PriorityQueue : Watch: $200 [Xbox: $300, IPad: $1200, IPone: $900] Element consumed from head of the PriorityQueue : Xbox: $300 [IPone: $900, IPad: $1200] Element consumed from head of the PriorityQueue : IPone: $900 [IPad: $1200]
從上面的輸出結果能夠很清晰的看到優先級對象始終把最小的值保存在頭部,它的排序規則取決於compareTo()方法,儘管它不必定全部元素都是按序排列的,可是它能保證隊列的頭必定是最小的元素,這也是TreeSet和PriorityQueue的區別,前者能保證全部元素按序排列,而優先級隊列僅僅保證列的頭是有序的,另外一個須要注意的地方是PriorityQueue並不容許null元素存在,若是嘗試添加null值,那麼就會拋出NullPointException異常:安全
Exception in thread "main" java.lang.NullPointerException at java.util.PriorityQueue.offer(PriorityQueue.java:265) at java.util.PriorityQueue.add(PriorityQueue.java:251) at test.PriorityQueueTest.main(PriorityQueueTest.java:36) Java Result: 1
總結:多線程
優先級隊列不是同步的,若是須要保證線程安全那麼請使用PriorityBlockingQueueide
隊列的獲取操做如poll(),peek()和element()是訪問的隊列的頭,保證獲取的是最小的元素(根據指定的排序規則)ui
返回的迭代器並不保證提供任何的有序性this
優先級隊列不容許null元素,不然拋出NullPointException。spa
以上全部就是有關優先級隊列的所有,它是一個很特別的類,用在一些特性的情景。記住:BlockingQueue維持的是插入的順序,若是想維持自定義的順序PriorityQueue或者PriorityBlockingQueue是正確的選擇,TreeSet提供相似的功能,可是沒有相似的檢索+移除的方法:poll()
原文連接: Javarevisited 翻譯: ImportNew.com - 劉志軍
譯文連接: http://www.importnew.com/6510.html
[ 轉載請保留原文出處、譯者和譯文連接。]