JDK源码系列——PriorityQueue源码解析


前言

优先级队列是包含0个或多个元素的集合,每个元素都一个权重值,每次出队弹出优先级最大或最小的元素,优先级队列是使用堆来实现了,所以大家看之间需要首先掌握堆结构。


1、主要属性分析

  1. queue:存储元素的数组
  2. comparator:比较器,在优先级队列中,每个元素都有权重值,也有两种比较元素大小的方式,一种是元素的自然顺序,一种是通过比较器来比较。
  3. modCount:修改次数,这个属性是为了fast-fail。

在这里插入图片描述

2、常用构造方法分析

这里提供了多个构造方法,你可以自己指定容量大小和比较器。

在这里插入图片描述

3、常用方法解析

3.1、入队方法

入队方法有两个,add方法和offer方法,add方法内部也是调用offer方法来实现的。offer方法执行步骤如下:

  1. 对元素做判空校验,不能插入空元素
  2. 判断当前数组是否满了,如果满了就先调用grow方法进行扩容
  3. 判断如果当前队列没有元素,那么就放到数组的第一个
  4. 如果当前队列有数据,那么调用siftUp方法插入到指定位置,然后做自下而上的堆化。

在这里插入图片描述

扩容方法,判断容量小于64那么每次扩容都是扩容2倍,当数组大于64那么每次扩容至增加一半,然后还会检查扩容后的容量有没有达到最大容量上限,有没有溢出等。

在这里插入图片描述

根据是否指定比较器调用不同的方法

在这里插入图片描述

这两个方法的区别就是在比较的是否是否使用自己指定的比较器。方法流程步骤如下:

  1. 这个传入的下标是当前队列的最后,首先找到父节点的位置,然后比较插入元素和父节点的值,如果小于父节点就和父节点交换位置(小顶堆),直到出现比父节点大为止。
  2. 两个方法的区别就是在于堆化的时候,和父节点比较的时候是采用默认比较还是指定比较器比较。

在这里插入图片描述在这里插入图片描述

3.2、出队方法

出队有两个方法,removepoll方法,remove也是调用的poll方法,只是在没有元素的时候抛出异常。poll方法步骤如下:

  1. 如果当前队列没有元素,则返回空
  2. 将队列首元素弹出,再把队列末元素移到队列首
  3. 调用siftDown方法做堆化。

在这里插入图片描述
在这里插入图片描述

这里做自上而下的堆化,根据是否有比较器调用不同的方法,这个我们已经知道内部逻辑一致,只是比较的时候是否用指定的比较器。我们看下siftDownComparable的方法执行流程:

  1. 这里因为堆是完全二叉树,所以叶子节点占了一半的元素,所以只需要比较一半就行了。
  2. 做自上而下堆化,一直往下与最小的子节点比较,如果比最小的字节点大,就叫唤位置,再继续与最小的子节点比较,如果比最小的子节点小,就不用交换位置了,堆化结束。

在这里插入图片描述在这里插入图片描述

3.3、查看堆顶元素

这里队列中的第一个就是堆顶元素

在这里插入图片描述

4、总结

PriorityQueue是一个小顶堆,他不是有序列表,只是通过堆化维持堆顶存储最大或最小的元素。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值