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
相关文章
相关标签/搜索