PriorityQueue理解

Posted yangfei629

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PriorityQueue理解相关的知识,希望对你有一定的参考价值。

1、并非按FIFO进出


传统的queue 是按先进先出的顺序执行。而PriorityQueue是按优先级来绝对的

优先级低的先出queue

 

2、如何排序


 

PriorityQueue既然有优先级排序 那么如何排序的。

a. 放入队列的元素实现了Comparable接口 按其自然顺序排序 从小到大。

b. 初始化队列时指明Comparator外部比较器。

PriorityQueue<String> queue1 = new PriorityQueue<>();
PriorityQueue<String> queue2 = new PriorityQueue<>(10);
PriorityQueue<String> queue3 = new PriorityQueue<>((a,b)->a.compareTo(b));

 

 

3、内部结构


 

内部使用数组存放元素:

transient Object[] queue;

数组默认容量11 (初始化时可以指定)  

 

动态扩容机制

容量<64 扩容为2*n+2,否则跟ArrayList一样扩大为1.5n

(64是一个权衡的不大不小的值)

private void grow(int minCapacity) 
        int oldCapacity = queue.length;
        // Double size if small; else grow by 50%
        int newCapacity = oldCapacity + ((oldCapacity < 64) ?
                                         (oldCapacity + 2) :
                                         (oldCapacity >> 1));
        // overflow-conscious code
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        queue = Arrays.copyOf(queue, newCapacity);
    

 

小根堆实现

小根堆:是一种完全二叉树 且满足父节点不大于任意一个左右子节点。(注意左右节点是没有顺序的)

所以小根堆的顶点必然是最小的 (如何要实现从大到小排序,指定的Comparator中取相反顺序即可)

而完全二叉树(所有节点满足从左到右排列 不会垮节点)是可以用数组表示的。

PriorityQueue就是使用数组来实现的小根堆: 满足每次取的数据都是最小的,但不满足整体都是有序的

技术图片

 

 

 

任意一个节点(数组中索引为n) 都可以知道其左右子节点和父节点在数组中的索引值:

父节点 : (n-1)/2

左子节点: 2n+1

右子节点:2n+2

  

关于节点的增删

增:在完全二叉树中依次创建一个新节点,再把新节点跟父节点依次比较,使其满足最小堆要求

删:删除的节点 用二叉树的最后一个节点先填充,再进行调整。

总是都是拿最有的节点处理,因为要满足完全二叉树。

具体细节网上例子很多 不再详解。

 

4、非线程安全


PriorityQueue的线程安全版本:PriorityBlockingQueue,使用ReentrantLock加锁保护

 

以上是关于PriorityQueue理解的主要内容,如果未能解决你的问题,请参考以下文章

深入理解Java PriorityQueue

PriorityQueue理解

Java 集合深入理解 :优先队列(PriorityQueue)之源码解读,及最小顶堆实现研究

PriorityQueue原理分析——基于源码

PriorityQueue,我错过了啥?

转:PriorityQueue