PriorityQueue和PriorityBlockingQueue

简介: PriorityQueue和PriorityBlockingQueue

目录



PriorityQueue和PriorityBlockingQueue


简介


Queue一般来说都是FIFO的,当然之前我们也介绍过Deque可以做为栈来使用。今天我们介绍一种PriorityQueue,可以安装对象的自然顺序或者自定义顺序在Queue中进行排序。


PriorityQueue


先看PriorityQueue,这个Queue继承自AbstractQueue,是非线程安全的。


PriorityQueue的容量是unbounded的,也就是说它没有容量大小的限制,所以你可以无限添加元素,如果添加的太多,最后会报OutOfMemoryError异常。


这里教大家一个识别的技能,只要集合类中带有CAPACITY的,其底层实现大部分都是数组,因为只有数组才有capacity,当然也有例外,比如LinkedBlockingDeque。


只要集合类中带有comparator的,那么这个集合一定是个有序集合。


我们看下PriorityQueue:


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


定义了初始Capacity和comparator,那么PriorityQueue的底层实现就是Array,并且它是一个有序集合。


有序集合默认情况下是按照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

相关文章
|
6月前
堆(优先级队列 PriorityQueue)
堆(优先级队列 PriorityQueue)
41 0
|
Java 调度
【PriorityQueue优先级队列及其应用】
【PriorityQueue优先级队列及其应用】
|
存储 安全 索引
认真研究队列中的优先级队列PriorityQueue
认真研究队列中的优先级队列PriorityQueue
75 0
|
存储 安全 Java
ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?
ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?
|
3月前
|
存储 设计模式 算法
【C++】deque以及优先级队列
【C++】deque以及优先级队列
|
6月前
|
存储 安全 Java
优先级队列
优先级队列
|
存储 Java
PriorityQueue优先级队列
PriorityQueue优先级队列
|
人工智能 算法 搜索推荐
我学会了,封装自己的优先队列PriorityQueue
优先队列本身就是一种队列。 普通队列:先进先出、后进后出,如排队买票吃饭一样。 优先队列:出队顺序和入队顺序无关,和优先级相关。如去医院看病,床位非常的紧张,需要排队才能去做手术的话,此时做手术的这个队伍的顺序就是一个优先队列。因为医生是根据每一个患者的病症的不同以及需要这个手术的紧急程度的不同来去安排谁先做手术谁后做手术,也可以认为每一个患者是有一个优先级的。优先级高者先得,这样的一个队列就叫做优先队列,它和普通队列最主要的区别是在于出队这个操作上,入队很简单,但是优先级高的先出队。
230 0
我学会了,封装自己的优先队列PriorityQueue
|
存储 算法 Java
PriorityQueue 源码分析
这两个函数其实就是首先将其他集合转化为连续的array,再将其堆化。
56 0
|
存储
优先级队列详解
优先级队列详解
113 0