【数据结构】关于Java对象比较,以及优先级队列的大小堆创建你了解多少???

前言:

🌟🌟Hello家人们,这期讲解对象的比较,以及优先级队列堆,希望你能帮到屏幕前的你。

🌈上期博客在这里:http://t.csdnimg.cn/MSex7

🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客

目录

📚️1. PriorityQueue中插入对象

📚️2元素的比较

2.1基本类型的比较

2.2对象比较问题

1.通过比较运算符

2.通过equals比较

📚️3.对象的比较

3.1重写基类的equals方法

3.2基于Comparble接口类的比较 

3.3基于比较器进行比较

3.4三种比较方式

📚️4.PriorityQueue的比较方式

4.1PriorityQueue的比较

4.2PriorityQueue大小堆解决topK问题

📚️总结


📚️1. PriorityQueue中插入对象

上期博客讲了优先级队列,优先级队列在插入元素时有个要求:插入的元素不能是null或者元素之间必须要能够进行比较,为了简单起见,我们只是插入了Integer类型,那优先级队列中能否插入自定义类型对象呢?

代码如下:

class Card {public int rank; // 数值public String suit; // 花色public Card(int rank, String suit) {this.rank = rank;this.suit = suit;}
}public class TestPriorityQueue {public static void TestPriorityQueue(){PriorityQueue<Card> p = new PriorityQueue<>();p.offer(new Card(1, "♠"));p.offer(new Card(2, "♠"));}public static void main(String[] args) {TestPriorityQueue();}
}

那么此时我们运行时就会抛出异常:

因为放置的元素必须要能够比较大小,不能插入无法比较大小的对象。在这里,小编给Card类初始化了它的大小,和花色使得在编译时,不知道该比较那个。

📚️2元素的比较

2.1基本类型的比较

在Java中基本数据类型可以直接进行比较,一般通过>,<或者==来进行判断,放回值为boolean类型,小编这里就不再过多解释,相信大家因该了解了。

2.2对象比较问题

1.通过比较运算符

代码如下:

        Student student=new Student(12,"zhangsan");Student student1=new Student(12,"zhangsan");System.out.println(student1==student);

此时输出的值为false;

因为在“==”在实质上是比较的两个对象的地址,很明显这两个同学并不是同一个地址的,他们两个都new了一个地址出来,所以该地输出为false。

2.通过equals比较

代码如下:

        Student student=new Student(12,"zhangsan");Student student1=new Student(12,"zhangsan");System.out.println(student1.equals(student));

此时输出为false;

在这里,我们可以通过内部原理进行解析:

对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equal方法,而==默认情况下调用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地址

内部原理代码如下:

在这里this为student1,因为是student1调用函数与另一个学生进行比较,此时student就为obj。那么结果到头来还是地址的比较,所以还是为不等false 。

📚️3.对象的比较

3.1重写基类的equals方法

代码如下:

class Student{public int age;public String name;public Student(int age,String name){this.age=age;this.name=name;}@Override                         //进行重写public boolean equals(Object o) {if (this == o) return true;if(o==null||!(o instanceof Student)){return false;}Student student=(Student) o;return age==student.age&&name==student.name;}
}

在这里第一个条件:如果是自己调用自己那么就一定相等

在这里第二个条件:如果括号里的对象是空的,或者不是student的子类,那么就不相等

在这里最后的情况:实现强转,并且通过调用其年龄,和名字进行比较,并返回,实现equals重写

覆写基类equal的方式虽然可以比较,但缺陷是:equal只能按照相等进行比较,不能按照大于、小于的方式进行比较 

3.2基于Comparble接口类的比较 

对用用户自定义类型,如果要想按照大小与方式进行比较时:在定义类时,实现Comparble接口即可,然后在类中重写compareTo方法。

代码如下:

class Card implements Comparable<Card>{public int rank;public String suit;public Card(int rank,String suit) {this.rank=rank;this.suit=suit;}public int compareTo(Card o){return rank-o.rank;}
}
public class test {public static void main(String[] args) {Card card=new Card(5,"♥");Card card1=new Card(5,"♥");System.out.println(card.compareTo(card1));}
}

在重写compareTo方法时,是通过两者的大小进行比较,返回如果是一个正数,那么前者比后者更大,反之如果为一个负数那么就是后者更大,为0那么表示两者相同。

3.3基于比较器进行比较

用户自定义比较器类,实现Comparator接口,并且重写Comparator中的compare方法

代码如下:

class Agecompare implements Comparator<Student>{public int compare(Student s1,Student s2){return s1.age-s2.age;}
}
class Namecompare implements Comparator<Student>{public int compare(Student s1,Student s2){return s1.name.compareTo(s2.name);}
}
public class test {public static void main(String[] args) {Agecompare agecompare=new Agecompare();Namecompare namecompare=new Namecompare();Student student2=new Student(12,"lisi");Student student3=new Student(12,"lisi");System.out.println(agecompare.compare(student2,student3));System.out.println(namecompare.compare(student2,student3));}
}

这里要单独定义类来实现接口,并且重写接口当中的方法,在进行比较时对定义的类进行实例化,并且通过对应对象调用重写的compare方法,然后传递参数即可。

注意:但是在用对像调用时,名字为string类不能够相减,此时string引用类型compareto方法进行比较。因为string实现了comparable接口,重写了compareto方法。

 

3.4三种比较方式

覆写的方法:
Object.equals

因为所有类都是继承自 Object 的,所以直接覆写即可,不过只能比较相等与否
Comparable.compareTo
需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序
Comparator.compare
需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强

📚️4.PriorityQueue的比较方式

4.1PriorityQueue的比较

当我们实现了compareor接口,并且重写了内部方法后,在PriorityQueue中如何实现添加对象呢?

代码如下:

class Agecompare implements Comparator<Student>{public int compare(Student s1,Student s2){return s1.age-s2.age;}
}
public class test {public static void main(String[] args) {Agecompare agecompare=new Agecompare();PriorityQueue<Student> p=new PriorityQueue<>(agecompare);p.offer(student);p.offer(student1);System.out.println(p.peek());p.poll();System.out.println(p.peek());}
}

此时我们需要实例化实现接口的类,并将比较器的实例作为参数传入,此时就能够传入学生对象了,但是输出是学生对象的地址,并没有实际意义。

4.2PriorityQueue大小堆解决topK问题

大小堆的接口实现:

class MaxHeap implements Comparator<Integer>{  //创建大堆public int compare(Integer o1,Integer o2){return o2-o1;}
}
class MinHeap implements Comparator<Integer>{  //创建小堆public int compare(Integer o1,Integer o2){return o1-o2;}
}

思路:在需要输出前K个最小的数目时,我们要创建大根堆,前k个数字组成的大根堆,当后面数字与堆顶元素比较时(堆顶元素最大)如果小于堆顶元素,那么就删除堆顶元素,将更小的元素传入堆中,那么在遍历完数组后,前K个组成的堆中就是最小的元素。

 代码如下:

class MintTopK {public void mink(int[] array,int k){if(k<=0){return;}MaxHeap maxHeap=new MaxHeap();PriorityQueue<Integer> q=new PriorityQueue<>(maxHeap);//创建一个大根堆(前k个值)for (int i = 0; i < k; i++) {q.offer(array[i]);}//堆剩下的数据进行操作for (int i = k; i < array.length ; i++) {if(array[i]<q.peek()){q.poll();q.offer(array[i]);}}//开始输出前k个数for (int i = 0; i <k ; i++) {int ret=q.poll();System.out.print(ret+" ");}}
}public class test {public static void main(String[] args) {int[] array={1,4,3,2,9};MintTopK mintTopK=new MintTopK();mintTopK.mink(array,3);}
}

那么此时的输出就为3  2  1

📚️总结

 💬💬小编这期主要讲解了对象的比较方式,以及优先级队列如何进行对象的插入,以及大小堆的创建,实现topK问题的解决。

对于优先级队列看似是二叉树的内容,但是实质上是数组的运用,在进行对象的比较时,也可以从源码进行理解,每种比较方式都有好坏,主要还是看情况哦~~~

🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!


                               💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。

                                                         😊😊  期待你的关注~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/404059.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode --- 410周赛

题目列表 3248. 矩阵中的蛇 3249. 统计好节点的数目 3250. 单调数组对的数目 I 3251. 单调数组对的数目 II 一、矩阵中的蛇 只要按照题目要求模拟即可&#xff0c;代码如下 class Solution { public:int finalPositionOfSnake(int n, vector<string>& commands…

9 算术、关系、逻辑、赋值、位操作、三元运算符及其优先级

目录​​​​​​​ 1 运算符基础 1.1 什么是运算符 1.2 什么是表达式 1.3 左操作数和右操作数 1.4 运算符分类 1.4.1 按照操作数个数分类 1.4.2 按照功能分类 1.5 如何掌握运算符 2 算术运算符 2.1 正号和负号 2.2 加、减、乘、除 2.3 取模&#xff08;取余&#…

Git的使用-初级

Git 主要可以使用的远程仓库有 Github &#xff0c;Gitee 如果在国内建议使用 Gitee 比较快 从远程仓库下载工程 在安装好了 Git 后&#xff0c;我们右键单击一个本地的文件夹作为下载的目的地&#xff0c;选择 Git Bash Here 便可以通过 Linux 命令行的形式操作 Git Linux…

Redis的基本概念和使用

目录 一、Redis简介 1、NOSQL 2、NOSQL和关系型数据库比较 3、主流的NOSQL产品 4、什么是Redis 5、启动Redis 二、Redis基本操作 1、大概操作 三、 Redis 数据类型&#xff08;5种常用&#xff09; 1、redis 数据存储格式 2、String 3、hash 4、list 5、Set 6、…

【Linux入门】Linux常见指令

目录 前言 一、Linux基本指令 1.ls指令 2.pwd命令 3.cd 指令 4.touch指令 5.mkdir指令 6.rmdir指令 && rm 指令 7.man指令 8.cp指令 9.mv指令 10.cat 11.date 12.top 13.shutdown-关机 14.重要的几个热键 二、Linux扩展指令 总结 前言 Linux指令是在…

自学编程从哪个语言入手比较好?

自学编程时选择哪个语言作为起点&#xff0c;仍然取决于你的个人兴趣、学习目标和职业规划。希望以下建议可以帮到你。 Python&#xff1a; 如果你对数据分析、机器学习、人工智能、Web 开发或自动化脚本编写等领域感兴趣&#xff0c;Python 是一个非常好的起点。它的语法简洁…

Charles 抓包工具的使用

Charles 是一个网络抓包工具&#xff0c;我们可以用它抓取 APP 运行过程中产生的所有请求内容和响应内容&#xff0c;这和在浏览器开发者工具的 Network 面板中看到网页产生的内容是一样的道理 Charles , Fiddler 等都是非常强大的 HTTP 抓包软件&#xff0c;功能基本类似&…

网站配置了https证书,但浏览器访问时却访问了http

是由于缺少强制将 HTTP 请求重定向到 HTTPS 的规则 # HTTP 到 HTTPS 重定向配置 server {listen 80;server_name www.xlqd.site xlqd.site;return 301 https://$host$request_uri; } # 那么你原来的server块就要删除 listen 80;

Linux系统之部署轻量级Markdown文本编辑器

Linux系统之部署轻量级Markdown文本编辑器 一、项目介绍1.1 项目简介1.2 使用方法 二、本次实践介绍2.1 本地环境规划2.2 本次实践介绍 三、检查本地环境3.1 检查系统版本3.2 检查系统内核版本3.3 检查软件源 四、安装Apache24.1 安装Apache2软件4.2 启动apache2服务4.3 查看ap…

【Nginx】Nginx 安装(平滑升级和回滚)

一、 Nginx 概述 Nginx 介绍 Nginx &#xff1a; engine X &#xff0c; 2002 年开发&#xff0c;分为社区版和商业版 (nginx plus ) 2019 年 3 月 11 日 F5 Networks 6.7 亿美元的价格收购 Nginx 是免费的、开源的、高性能的 HTTP 和反向代理服务器、邮件代理服务器、以…

【word】修改图名/表名/公式编号后快速更新交叉引用的内容;交叉引用的字体不跟随正文如何解决

本文解决两个问题&#xff0c;不是什么特别正规的方法&#xff0c;主打一个迅速且通用。 问题描述 修改图名/表名/方程编号后快速更新交叉引用的内容 假设我们现在word文档中某处用了交叉引用。显然&#xff0c;图 1两个字颜色更深&#xff0c;就是我交叉引用的地方。 由于某…

贝莱德与摩根大通的最新季度持仓分析

近期&#xff0c;华尔街的两大投资巨头贝莱德和摩根大通公布了其2024年第二季度的13F报告&#xff0c;揭示了他们在投资组合上的最新动向。通过分析这些持仓数据&#xff0c;我们可以更清楚地了解这些顶级投资机构的投资策略和市场偏好。 贝莱德的科技巨头与能源投资 根据贝莱…

SpringBoot教程(二十二) | SpringBoot实现分布式定时任务之elastic-job

SpringBoot教程&#xff08;二十二&#xff09; | SpringBoot实现分布式定时任务之elastic-job 简介前置条件&#xff1a;需要ZooKeeper配合1、引入相关依赖2、application.yml中配置注册中心和作业调度巨坑&#xff08;配置修改无效&#xff09;3、job实例4、ElasticJob-UI监控…

网络编程-网络基础

IO进程: 进程和进程之间的通信 - 信号 信号量 消息队列 有名管道 无名管道 共享内存 套接字 套接字: 不同主机 不同操作系统之间的 进程通信 干什么: 实现无线 局域网&#xff1a;同一局域网下IP网段一致 IP地址 1) IP地址 是 网络中的 主机的标识, 本质是二进制数字。 2…

37_DC-5靶机渗透测试、nmap使用、kail漏洞库使用、系统提权、反弹shell到kali、留后门、蚁剑连接webshell、文件包含漏洞利用、NC用法

环境准备 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/dc-5,314/ 百度网盘&#xff1a;https://pan.baidu.com/s/1lqFMjoqQpIl4DA-Amb00pA?pwd9LJY 攻击机&#xff1a;kali&#xff08;192.168.58.130&#xff0c;IP是各自不同的&#xff09; 靶机&#xff1…

SystemUI手势操作隐藏显示导航栏

在Android 12中&#xff0c;通过SystemUI手势操作来隐藏和显示导航栏主要涉及对系统UI的定制和编程控制。以下是一些实现这一功能的方法&#xff1a; 默认是隐藏 向上滑动 第一类. 使用WindowInsetsController Android 12引入了一个新的WindowInsetsController类&#xff0c;它…

【数据分享】1999—2022年地级市地区生产总值及一二三产构成数据(Shp/Excel格式)

在之前的文章中&#xff0c;我们分享过基于2000-2023年《中国城市统计年鉴》整理的1999-2022年地级市的人口相关数据、各类用地面积数据、污染物排放和环境治理相关数据、房地产投资情况和商品房销售面积、社会消费品零售总额和年末金融机构存贷款余额、一般公共预算收支状况、…

bootchart抓Android系统启动各阶段性能数据

最近在做Android系统启动优化&#xff0c;首要任务是找到启动过程中各阶段耗时点&#xff0c;进而有针对性地进行优化。主要用bootchart抓开机数据&#xff0c;本文主要记录下工具的使用方法。 1.抓开机数据 adb root adb shell ‘touch /data/bootchart/enabled’ adb rebo…

STM32标准库学习笔记-6.定时器-输入捕获

参考教程&#xff1a;【STM32入门教程-2023版 细致讲解 中文字幕】 定时器输入捕获 IC&#xff08;Input Capture&#xff09;输入捕获输入捕获模式下&#xff0c;当通道输入引脚出现指定电平跳变时&#xff0c;当前CNT的值将被锁存到CCR中&#xff0c;可用于测量PWM波形的频率…

8.14-LVS主从+nginx的haproxy+mysql的haproxy+读写分离

一、LVS-主从数据库 # nat # 添加规则 [rootDS ~]# ipvsadm -A -t 192.168.2.130:3306 -s rr [rootDS ~]# ipvsadm -a -t 192.168.2.130:3306 -r 192.168.2.40:3306 -m [rootDS ~]# ipvsadm -a -t 192.168.2.130:3306 -r 192.168.2.42:3310 -m [rootDS ~]# ipvsadm -Ln IP Vir…