深入理解PriorityQueue的特性

这篇具有很好参考价值的文章主要介绍了深入理解PriorityQueue的特性。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

深入理解PriorityQueue的特性

一、PriorityQueue的特性

Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的
深入理解PriorityQueue的特性
使用操作:
1.在我们使用优先级队列时,必须导入相应的包
深入理解PriorityQueue的特性
2.PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出ClassCastException异常
让我们深入了解一下这个问题。

class Person {
    int age;
    String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
}
public class Test {
    public static void main(String[] args) {
        PriorityQueue<Person> priorityQueue = new PriorityQueue<>();
        priorityQueue.offer(new Person(18,"张三"));
    }
}

我们试着只插入一个元素,发现并没有报错。
深入理解PriorityQueue的特性

public static void main(String[] args) {
        PriorityQueue<Person> priorityQueue = new PriorityQueue<>();
        priorityQueue.offer(new Person(18,"张三"));
        priorityQueue.offer(new Person(20,"李四"));
    }

深入理解PriorityQueue的特性
我们发现当我们插入第二个元素的时候,系统报了类转换异常,那是为什么呢?我们上升到源码的层次上去分析一下。
深入理解PriorityQueue的特性
当我们只传入一个参数时,系统默认调用两个参数的构造方法。
深入理解PriorityQueue的特性
第一个参数是一个静态常量,默认为11.
深入理解PriorityQueue的特性
指定此队列容量为11,comparator为null。
深入理解PriorityQueue的特性
直到这里构造方法就完成了,接下来我们再看一下系统的offer方法。
深入理解PriorityQueue的特性
我们可以发现,当我们传入第一个元素时,它直接赋值,没有进行其他操作,这也是我们为什么刚在插入第一个元素时没有报错的原因。
深入理解PriorityQueue的特性
我们再来看插入不为第一个元素时是什么情况,这里我们的comparator为null,所以进入第二个方法。
深入理解PriorityQueue的特性
我们发现当插入时,会将我们传入的元素强制转换为Comparable接口,但是我我们的类并没有实现这个接口,所以会报类转换异常。
所以我们想插入多个元素时,对应的类比较实现相应的接口和方法。

class Person implements Comparable<Person>{
    int age;
    String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    public int compareTo(Person o) {
        return this.age - o.age;
    }
}
public class Test {
    public static void main(String[] args) {
        PriorityQueue<Person> priorityQueue = new PriorityQueue<>();
        priorityQueue.offer(new Person(20,"李四"));
        priorityQueue.offer(new Person(18,"张三"));
        System.out.println("=============================");
    }
}

深入理解PriorityQueue的特性
这样就可以正常操作了。

3. 不能插入null对象,否则会抛出NullPointerException
深入理解PriorityQueue的特性
4. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容
深入理解PriorityQueue的特性
我们可以发现,每次插入的时候,系统都会判断一个这个优先级队列是否为满,如果满了就grow。
深入理解PriorityQueue的特性
当你的优先级队列容量小于64时,进行2倍+2扩容,如果大于64时,进行1.5倍扩容。
深入理解PriorityQueue的特性
对扩容后的大小进行判断,当大于2147483639时,就会重新计算。深入理解PriorityQueue的特性
深入理解PriorityQueue的特性
如果传入的容量大小大于2147483639时,赋值为2147483647,否则赋值为2147483639。

5. 插入和删除元素的时间复杂度为O(logn)
上一篇文章我们深入讲过元素的插入和删除的时间复杂度。

6. PriorityQueue底层使用了堆数据结构, (注意:此处大家可以不用管什么是堆,后文中有介绍)
7. PriorityQueue默认情况下是小堆—即每次获取到的元素都是最小的元素
深入理解PriorityQueue的特性
是我们在向上操作时的判断条件,在后面我们想建大根堆时,也会灵活变通。

二、 PriorityQueue的构造方法。

无参构造

创建一个空的优先级队列,默认容量是11,上面我们具体讲过,这里就不在一一阐述。

指定容量

PriorityQueue(int initialCapacity)创建一个初始容量为initialCapacity的优先级队列,注意:initialCapacity不能小于1,否则会抛IllegalArgumentException异常
深入理解PriorityQueue的特性
深入理解PriorityQueue的特性

传入比较器

public PriorityQueue(int initialCapacity, Comparator<? super E> comparator)
深入理解PriorityQueue的特性
当我们传入指定的比较器之后,我们就可以按照指定比较方式进行插入比较,先来举一个简单的例子。

class Student{
    String name;
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
class ageComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}
    public static void main(String[] args) {
        PriorityQueue<Student> priorityQueue = new PriorityQueue<>(2,new ageComparator());
        priorityQueue.offer(new Student("李四",20));
        priorityQueue.offer(new Student("张三",18));
        System.out.println("---------------");
    }

在这里我们实现一个比较器,然后传入,可以正常操作。
深入理解PriorityQueue的特性
这样单独写一个类太麻烦了,有没有简单一点的操作。

public static void main(String[] args) {
        PriorityQueue<Student> priorityQueue = new PriorityQueue<>(2, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.age - o2.age;
            }
        });
        priorityQueue.offer(new Student("李四",20));
        priorityQueue.offer(new Student("张三",18));
        System.out.println("---------------");
    }

这里我们使用了一下匿名内部类来实现比较器。
深入理解PriorityQueue的特性

那如何建立一个大根堆呢?

深入理解PriorityQueue的特性
我们分析源码时,我们发现这里决定着向上操作的判断决定着我们建立的是大根堆还是小根堆。我们只需要在传入比较器中的条件即可。

public static void main(String[] args) {
        PriorityQueue<Student> priorityQueue = new PriorityQueue<>(2, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.age - o1.age;
            }
        });
        priorityQueue.offer(new Student("李四",20));
        priorityQueue.offer(new Student("张三",18));
        System.out.println("---------------");
    }

深入理解PriorityQueue的特性
深入理解PriorityQueue的特性
这样就成功创建了一个大根堆了。文章来源地址https://www.toymoban.com/news/detail-426670.html

三、 PriorityQueue常用操作

函数名 功能介绍
boolean
offer(E e) 插入元素e,插入成功返回true,如果e对象为空,抛出NullPointerException异常,时间复杂度 ,注意:空间不够时候会进行扩容
E peek() 获取优先级最高的元素,如果优先级队列为空,返回null
E poll() 移除优先级最高的元素并返回,如果优先级队列为空,返回null
int size() 获取有效元素的个数
void clear() 清空
boolean isEmpty() 检测优先级队列是否为空,空返回true
上一篇中我们已经一一实现,在这里我们就不再进行操作了。

到了这里,关于深入理解PriorityQueue的特性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++:深入理解C++11新特性:Chapter3:左值和右值

    在C语言中,我们常常会提起左值(lvalue),右值(rvalue)这样的称呼,而在编译程序时,编译器有时也会报出错误信息中包含 左值,右值说法。不过左值、右值通常不是通过一个严谨的定义而为人所知。下面我通过这样一个例子,来引导大家认识: 左值,右值,左值引用,右

    2024年02月04日
    浏览(33)
  • 重温《深入理解Java虚拟机:JVM高级特性与最佳实践(第二版)》 –– 学习笔记(一)

    第1章:走近Java 1.1 Java的技术体系 SUN 官方所定义的 Java 技术体系包括:Java程序设计语言、Java虚拟机、Class文件格式、Java API类库、第三方(商业机构和开源社区)Java类库。 其中,「Java程序设计语言」、「Java虚拟机」、「Java API类」这三个被称为 JDK(Java Deployment Kit),即

    2024年01月23日
    浏览(40)
  • 深入分析Java中的PriorityQueue底层实现与源码

    本文分享自华为云社区《滚雪球学Java(70):深入理解Java中的PriorityQueue底层实现与源码分析》,作者: bug菌。 @[toc] PriorityQueue是Java中一个非常常用的数据结构,它可以实现基于优先级的排序,常用于任务调度、事件处理等场景。本文将深入探讨Java中PriorityQueue的底层实现与源

    2024年03月19日
    浏览(35)
  • 深入理解ArkTS:Harmony OS 应用开发语言 TypeScript 的基础语法和关键特性

    Harmony OS应用开发的主力语言ArkTS的前身TS语言的基本语法。通过学习变量的声明和数据类型、条件控制、函数声明、循环迭代等基本知识,并了解内核接口的声明和使用。同时还介绍了模块化开发的概念,提高代码的复用性和开发效率。该对话还涉及了if else和switch条件控制语

    2024年02月04日
    浏览(40)
  • 《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) 周志明》 - 第12章代码示例

            最近在看《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) 周志明》这本书,书中有些代码示例是为了让读者理解作者表达的意思,但不是完整的代码示例,所以针对这些不完整的代码,自己动手写出完整的代码示例。 (1)在看这本书的同学,可以拿我这里的示

    2024年01月22日
    浏览(37)
  • 理解 Redis 新特性:Stream

    该数据结构需要 Redis 5.0.0 + 版本才可用使用 Redis stream 是 Redis 5 引入的一种新的数据结构,它是一个高性能、高可靠性的消息队列,主要用于异步消息处理和流式数据处理。在此之前,想要使用 Redis 实现消息队列,通常可以使用例如:列表,有序集合、发布与订阅 3 种数据结

    2023年04月17日
    浏览(31)
  • 理解Mysql索引原理及特性

    作为开发人员,碰到了执行时间较长的sql时,基本上大家都会说”加个索引吧”。但是索引是什么东西,索引有哪些特性,下面和大家简单讨论一下。 索引就好比书本的目录,提高数据库表数据访问速度的数据库对象。当我们的请求打过来之后,如果有目录,就会快速的定位

    2024年02月05日
    浏览(28)
  • 如何理解闭包函数的特性(golang版)

    特性:闭包可以在多次调用之间保持原始状态 我们来看一个例子: 在这个例子中,我们可以将函数 func makeAdder(base int) func(int) int 拆成两部分,分别为: func makeAdder(base int) func(int) int 匿名函数 func(int) int 充当了 makeAdder 函数的返回值。 即 makeAdder 函数接收了一个整数作为参数

    2024年02月16日
    浏览(35)
  • 【Python 高级特性】深入 NamedTuple 命名元组

    和元组 tuple 一样,NamedTuple 也是 不可变数据类型 ,创建之后就不能改变内容。 如其名,和 tuple 的区别在于“Named”,即\\\"命名\\\"。 NamedTuple 不像数组那样使用下标读写,反而和类相似,使用 . 来读写。 创建 NamedTuple 的函数定义 参数说明: typename :新创建的类的名称。 field_

    2024年04月11日
    浏览(31)
  • Unity中的InitializeOnLoad特性:深入解析与实践

    在Unity开发过程中,我们经常需要在编辑器启动时或脚本重新编译后执行一些操作,例如初始化数据、注册事件等。这时,我们可以使用 InitializeOnLoad 特性来实现这一需求。本文将详细介绍 InitializeOnLoad 特性的用法,并通过三个实际案例来展示其应用场景。 InitializeOnLoad 是U

    2024年02月06日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包