栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

文章目录
  • 前言
  • 1、主要属性分析
  • 2、常用构造方法分析
  • 3、常用方法解析
    • 3.1、入队方法
    • 3.2、出队方法
    • 3.3、查看堆顶元素
  • 4、总结


前言

优先级队列是包含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、出队方法

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

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


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

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

3.3、查看堆顶元素

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

4、总结

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1003423.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号