什麼是Java優先級隊列?

PriorityQueue是基於無界優先級隊列和優先級堆構建的重要Java API之一。本文經過適當的代碼示例深刻了解了有關此API及其用法的一些複雜信息。另在上篇文章中咱們簡單地談了下Java編譯器API簡介,你能夠先閱讀以方便更好地閱讀這篇文章。感謝優銳課老師對我寫下這兩篇文章時給予的幫助。html

 

總覽

PriorityQueue類是java.util包的一部分,是Java中基於優先級的隊列的通用實現。隊列基本上是一種數據結構,它定義了針對商店中商品的插入和檢索過程的特定規範。這個想法與排隊等候說票的許多人很是類似。排隊的第一我的有第一個得到彩票的機會,最後一我的有一個結局的機會。人們被添加到隊列的末尾或末尾。在隊列中添加項目在技術上稱爲入隊過程,從隊列中刪除的項目是從該行的第一行開始。這稱爲出隊。想法是以先進先出的方式對元素進行排序。java

如今,這是最簡單的體系結構,而且緊密定義了隊列的實際含義以及如何在計算機中模擬隊列。存儲一般由一個簡單的數組表示,其中存儲和檢索過程具備此定義的規範。優先級隊列在此之上強加一些特殊規範。咱們將在後面看到更多內容。程序員

 

隊列的Java實現

Java API在java.util包中具備通用接口名稱Queue <E>。這是Java Collection Framework API的一部分,旨在在處理以前保存元素。做爲集合的一部分,它具備全部基本的集合操做。特定於其標識的操做涉及存儲在其中的元素的插入,提取和檢查。這些操做中的每個都有兩種不一樣的形式,例如一種在操做失敗時引起異常,而另外一種則根據操做返回一個特殊值,例如null或false。請注意,與典型隊列不一樣,Java Queue的具體實現沒必要必定以FIFO方式對元素進行排序。對於基於優先級的隊列尤爲如此,其中元素的排序是根據提供的比較器或天然排序完成的。可是不管順序如何,remove()或poll()方法將始終檢索隊列開頭的元素。這兩種不太可能的方法之間的特定區別彷佛是一種類似的方法,即在失敗時引起異常(NoSuchElementException),然後者則返回特殊值(null)。編程

 

方法數組

引起異常安全

描述數據結構

 

E remove()併發

NoSuchElementExceptionide

從隊列的開頭檢索一個元素。函數

 

void add(E)

IllegalStateException

在隊列末尾插入一個元素。成功返回true,若是空間不可用則拋出異常。

 

E element()

NoSuchElementException

檢索元素而不將其從隊列的開頭移除。

 

 

 

 

 

 

方法

返回特殊值

說明

boolean offer(E)

true or false

將元素插入隊列。成功返回true,若是因爲空間不足而沒法插入,則返回false。

E poll()

null

從隊列的開頭移除元素;若是隊列爲空,則返回null。

E peek()

null

檢索但不從隊列的開頭刪除元素。若是隊列爲空,則返回null。

           

請注意,Queue <E>接口不適用於併發編程,由於它沒有定義阻塞隊列方法,在這種方法中,入隊和出隊過程等待元素出如今隊列中或大小可用。有一個名爲BlockingQueue <E>的特定接口,該接口擴展了Queue <E>接口並解決了這些問題。

有一個稱爲AbstractQueue <E>的抽象類,該類提供某些隊列操做的部分實現。 PriorityQueue <E>類是此抽象類的直接擴展。

 

優先隊列

優先級隊列的Java實現是一種特殊的隊列,其中元素的排序由其天然排序原則肯定,也能夠根據建立期間提供的Comparator進行定製。咱們在構造過程當中調用的構造函數決定要與優先級隊列一塊兒使用的排序原則。與不容許使用null元素的Queue <E>不一樣,可是某些實現(例如LinkedList)也不由止插入null元素。可是,PriorityQueue <E>根本不容許空元素。若是優先級隊列是根據天然順序構造的,則任何不可比較的元素插入都將引起ClassCastException。

它被聲明爲無限制的而且基於優先級堆。儘管隊列的大小被稱爲無限制,但內部具備肯定陣列大小的能力。插入元素時,此大小會自動增加。可是,沒有詳細說明增大尺寸的原理。

有七種類型的重載構造函數,經過它們咱們能夠設置參數來指定隊列的初始容量,提供Comparator來指定元素的自定義順序,或者使用無參數構造函數將全部內容接受爲默認值。

  • PriorityQueue()
  • PriorityQueue(int initialCapacity)
  • PriorityQueue(int initialCapacity, Comparator<? Super E> comparator)
  • PriorityQueue(Commection<? extends E> c)
  • PriorityQueue(Comparator<? Super E> comparator)
  • PriorityQueue(PriorityQueue<? extends E> c)
  • PriorityQueue(SortedSet<? extends E> c)

與Queue <E>類似,PriorityQueue <E>也不一樣步,所以在併發編程中應謹慎使用。可是,有一個同步的替代方法,稱爲PriorityBlockingQueue <E>。這與PriorityQueue <E>的工做方式相同,只是具備線程安全的其餘限定條件。

PriorityQueue <E>中定義的操做與Queue <E>相同,但有一些附加功能。

方法

描述

void clear()

從優先級隊列中刪除全部元素。

Comparator<? Super E> comparator()

返回與隊列關聯的比較器。若是根據天然順序對隊列進行排序,則返回null。

boolean contains(Object o)

若是隊列包含指定的對象,則返回true。

Iterator<E> iterator()

返回與Collection類關聯的舊式迭代器。可是,它不能保證以任何特定順序遍歷元素。

Spliterator<E> spliterator()

建立後期綁定,故障快速拆分器,但具備與迭代器相同的條件。

Object[] toArray()

這是一種便捷方法,可用於設置遍歷順序權限,例如Arrays.sort(priorityQueue.toArray()).

<T>T[] toArray(T[] a)

返回數組元素,可是返回類型由指定的數組肯定。

 

快速示例1

讓咱們用一個簡單的程序實現PriorityQueue <E>的一些操做。

 1 package org.mano.examples;
 2 import java.util.Arrays;
 3 import java.util.Iterator;
 4 import java.util.PriorityQueue;
 5 public class Example1 {
 6    public static void main(String[] args){
 7       PriorityQueue<String> pq = new PriorityQueue<>();
 8       pq.add("Mercury");
 9       pq.add("Venus");
10       pq.add("Earth");
11       pq.add("Mars");
12       pq.add("Jupiter");
13       pq.add("Saturn");
14       // Get the most priority element based upon
15       // natural alphabetic ordering in string
16       System.out.println("Priority element "+pq.peek());
17       // Queue elements
18       show(pq);
19       // Remove top of the queue element
20       pq.poll();
21       show(pq);
22       // Retrieves element from the head of the queue
23       pq.remove("Earth");
24       show(pq);
25       String result = pq.contains("Earth")?
26          "Found Earth":"Earth Missing!";
27       System.out.println(result);
28       Object[] arr = pq.toArray();
29       Arrays.sort(arr);
30       System.out.println("");
31       for (int i = 0; i<arr.length; i++)
32          System.out.print(arr[i].toString()+"::");
33    }
34    public static void show(PriorityQueue<String> pq){
35       Iterator<String> itr = pq.iterator();
36       while (itr.hasNext())
37          System.out.print(itr.next()+"::");
38          System.out.println("");
39    }
40 }

 

Output

1 Priority element Earth
2 Earth::Jupiter::Mercury::Venus::Mars::Saturn::
3 Jupiter::Mars::Mercury::Venus::Saturn::
4 Jupiter::Mars::Mercury::Venus::Saturn::
5 Earth Missing!
6  
7 Jupiter::Mars::Mercury::Saturn::Venus::

 

快速示例2

這是另外一個帶有自定義比較器的快速示例。

 1 package org.mano.examples;
 2 import java.util.Comparator;
 3 import java.util.PriorityQueue;
 4 public class Planet implements Comparable<Planet>{
 5    private String name;
 6    private double orbitPeriodInDays;
 7    public Planet(String name, double orbitPeriodInDays) {
 8       this.name = name;
 9       this.orbitPeriodInDays = orbitPeriodInDays;
10    }
11    public String getName() {
12       return name;
13    }
14    public void setName(String name) {
15       this.name = name;
16    }
17    public double getOrbitPeriodInDays() {
18       return orbitPeriodInDays;
19    }
20    public void setOrbitPeriodInDays(double orbitPeriodInDays) {
21       this.orbitPeriodInDays = orbitPeriodInDays;
22    }
23    @Override
24    public int compareTo(Planet o) {
25       return 0;
26    }
27    @Override
28    public String toString() {
29       return "Planet{" +
30          "name='" + name + '\'' +
31          ", orbitPeriodInDays=" + orbitPeriodInDays +
32          '}';
33    }
34    public static void main(String[] args){
35       Comparator<Planet> nameSorter =
36          Comparator.comparing(Planet::getName);
37       PriorityQueue<Planet> priorityQueue = new
38          PriorityQueue<>(nameSorter);
39       priorityQueue.add(new Planet("Mercury",88));
40       priorityQueue.add(new Planet("Venus",225));
41       priorityQueue.add(new Planet("Earth",365.24));
42       priorityQueue.add(new Planet("Mars",693.5));
43       priorityQueue.add(new Planet("Jupiter",4343.5));
44       priorityQueue.add(new Planet("Saturn",10767.5));
45       priorityQueue.add(new Planet("Uranus",30660));
46       priorityQueue.add(new Planet("Neptune",60152));
47       Object[] list = priorityQueue.toArray();
48       for (Object o: list)
49          System.out.println(o);
50    }
51 }

 

Output

1 Planet{name='Earth', orbitPeriodInDays=365.24}
2 Planet{name='Jupiter', orbitPeriodInDays=4343.5}
3 Planet{name='Mercury', orbitPeriodInDays=88.0}
4 Planet{name='Neptune', orbitPeriodInDays=60152.0}
5 Planet{name='Mars', orbitPeriodInDays=693.5}
6 Planet{name='Saturn', orbitPeriodInDays=10767.5}
7 Planet{name='Uranus', orbitPeriodInDays=30660.0}
8 Planet{name='Venus', orbitPeriodInDays=225.0}

 

總結

優先級隊列的其餘規範是,從列表中刪除的項目具備最高優先級。Java將優先級規則強加給其餘常規隊列的方式是經過附加元素的排序原則。該順序能夠根據程序員的要求進行自定義,也能夠設置爲默認。這就是Java中優先級隊列實現的本質。

感謝閱讀!

相關文章
相關標籤/搜索