PriorityQueue和PriorityBlockingQueue

PriorityQueue和PriorityBlockingQueuejava

簡介

Queue通常來講都是FIFO的,固然以前咱們也介紹過Deque能夠作爲棧來使用。今天咱們介紹一種PriorityQueue,能夠安裝對象的天然順序或者自定義順序在Queue中進行排序。git

PriorityQueue

先看PriorityQueue,這個Queue繼承自AbstractQueue,是非線程安全的。github

PriorityQueue的容量是unbounded的,也就是說它沒有容量大小的限制,因此你能夠無限添加元素,若是添加的太多,最後會報OutOfMemoryError異常。數組

這裏教你們一個識別的技能,只要集合類中帶有CAPACITY的,其底層實現大部分都是數組,由於只有數組纔有capacity,固然也有例外,好比LinkedBlockingDeque。安全

只要集合類中帶有comparator的,那麼這個集合必定是個有序集合。this

咱們看下PriorityQueue:線程

private static final int DEFAULT_INITIAL_CAPACITY = 11;
 private final Comparator<? super E> comparator;

定義了初始Capacity和comparator,那麼PriorityQueue的底層實現就是Array,而且它是一個有序集合。code

有序集合默認狀況下是按照natural ordering來排序的,若是你傳入了 Comparator,則會按照你指定的方式進行排序,咱們看兩個排序的例子:對象

@Slf4j
public class PriorityQueueUsage {

    @Test
    public void usePriorityQueue(){
        PriorityQueue<Integer> integerQueue = new PriorityQueue<>();

        integerQueue.add(1);
        integerQueue.add(3);
        integerQueue.add(2);

        int first = integerQueue.poll();
        int second = integerQueue.poll();
        int third = integerQueue.poll();

        log.info("{},{},{}",first,second,third);
    }

    @Test
    public void usePriorityQueueWithComparator(){
        PriorityQueue<Integer> integerQueue = new PriorityQueue<>((a,b)-> b-a);
        integerQueue.add(1);
        integerQueue.add(3);
        integerQueue.add(2);

        int first = integerQueue.poll();
        int second = integerQueue.poll();
        int third = integerQueue.poll();

        log.info("{},{},{}",first,second,third);
    }
}

默認狀況下會按照升序排列,第二個例子中咱們傳入了一個逆序的Comparator,則會按照逆序排列。排序

PriorityBlockingQueue

PriorityBlockingQueue是一個BlockingQueue,因此它是線程安全的。

咱們考慮這樣一個問題,若是兩個對象的natural ordering或者Comparator的順序是同樣的話,兩個對象的順序仍是固定的嗎?

出現這種狀況,默認順序是不能肯定的,可是咱們能夠這樣封裝對象,讓對象能夠在排序順序一致的狀況下,再按照建立順序先進先出FIFO的二次排序:

public class FIFOEntry<E extends Comparable<? super E>>
        implements Comparable<FIFOEntry<E>> {
    static final AtomicLong seq = new AtomicLong(0);
    final long seqNum;
    final E entry;
    public FIFOEntry(E entry) {
        seqNum = seq.getAndIncrement();
        this.entry = entry;
    }
    public E getEntry() { return entry; }
    public int compareTo(FIFOEntry<E> other) {
        int res = entry.compareTo(other.entry);
        if (res == 0 && other.entry != this.entry)
            res = (seqNum < other.seqNum ? -1 : 1);
        return res;
    }
}

上面的例子中,先比較兩個Entry的natural ordering,若是一致的話,再按照seqNum進行排序。

本文的例子https://github.com/ddean2009/learn-java-collections

歡迎關注個人公衆號:程序那些事,更多精彩等着您!
更多內容請訪問 www.flydean.com
相關文章
相關標籤/搜索