本人是一个刚刚上路的IT新兵,菜鸟!分享一点自己的见解,如果有错误的地方欢迎各位大佬莅临指导,如果这篇文章可以帮助到你,劳请大家点赞转发支持一下!
上一篇文章,讲解了优先级队列,从这里开始就对插入的数据有要求了,那就是插入的数据必须可以比较,有优先级之分。并且以后要用到比较的地方也越来越多,所以今天就来讲一讲java对象的比较
优先级队列在插入元素时有个要求:插入的元素不能是null或者元素之间必须要能够进行比较,那么我们要如何让插入的对象实现比较功能呢?
class Student {
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Compare {
public static void main(String[] args) {
Student stu1 = new Student("小明",15);
Student stu2 = new Student("小红",16);
PriorityQueue<Student> priorityQueue = new PriorityQueue<>();
priorityQueue.offer(stu1);
priorityQueue.offer(stu2);
}
}
运行上述代码时,会抛出运行时异常。
优先级队列底层使用堆,而向堆中插入元素时,为了满足堆的性质,必须要进行元素的比较,而此时Student是没有办法直接进行比较的,因此抛出异常。
在Java中,基本类型的对象可以直接比较大小。
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println(a > b);
System.out.println(a < b);
System.out.println(a == b);
char c1 = 'A';
char c2 = 'B';
System.out.println(c1 > c2);
System.out.println(c1 < c2);
System.out.println(c1 == c2);
boolean b1 = true;
boolean b2 = false;
System.out.println(b1 == b2);
System.out.println(b1 != b2);
}
class Student {
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
Student student1 = new Student("小明",15);
Student student2 = new Student("小红",15);
Student student3 = student1;
//System.out.println(student1 > student2);
//编译报错
System.out.println(student1 == student2);
//编译成功,打印false,因为student1和student2指向的是不同对象
System.out.println(student1 == student3);
//编译成功,打印true,因为student1和student2指向的是同一个对象
}
那为什么 == 可以比较呢?
对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equal方法,而==默认情况下调用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地
址。
Object中equal的实现,是直接比较的是两个引用变量是否指向同一个地址
class Student {
public String name;
public int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
//如果是同一个对象,返回true
if (o == null || getClass() != o.getClass()) return false;
//如果为空或不是同一类型,返回false
Student student = (Student) o;
//强转后,比较,这里认为只要姓名年龄相同就是一个人
return age == student.age && Objects.equals(name, student.name);
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
Student student1 = new Student("小明",15);
Student student2 = new Student("小红",15);
System.out.println(student1 == student2);//重写了equals,返回true
}
}
覆写基类equal的方式虽然可以比较,但缺陷是:equal只能按照相等进行比较,不能按照大于、小于的方式进行比较。
Comparble是JDK提供的泛型的比较接口类,源码如下:
compareTo返回一个值
这个值 < 0: 表示 this 指向的对象小于 o 指向的对象
这个值 == 0: 表示 this 指向的对象等于 o 指向的对象
这个值 > 0: 表示 this 指向的对象大于 o 指向的对象
对用用户自定义类型,如果要想按照大小与方式进行比较时:在定义类时,实现Comparble接口即可,然后在类中重写compareTo方法。
class Student implements Comparable<Student>{
public String name;
public int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Student o) {
//默认null最小
if(o == null) {
return 1;
}
//自己定义如何比较大小
//return this.age - o.age;//凭年龄比较大小
return this.name.compareTo(o.name);//凭姓名比较大小
//String类自身就重写了compareTo方法,会优先调用自己的
}
public static void main(String[] args) {
Student student1 = new Student("小明",15);
Student student2 = new Student("小红",15);
System.out.println(student1.compareTo(student2));
// == 0,表示是一个同学
// < 0,表示 student1 比较小
// > 0,表示 student1 比较大
}
}
Compareble是java.lang中的接口类,可以直接使用。
用这种写法呢,就将比较方式写死了,就不能再通过其他属性来比较了,侵略性强。
class Student {
public String name;
public int age;
}
//基于姓名的比较器
class NameComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
//基于年龄的比较器
class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
可以看到两个比较器都实现了Comparator接口,并重写了compare方法。
public static void main(String[] args) {
Student student1 = new Student("小明",15);
Student student2 = new Student("小红",15);
//创建比较器对象
AgeComparator ageComparator = new AgeComparator();
NameComparator nameComparator = new NameComparator();
int flg1 = ageComparator.compare(student1,student2);
System.out.println(flg1);
int flg2 = nameComparator.compare(student1,student2);
System.out.println(flg2);
// == 0,表示是一个同学
// < 0,表示 p 比较小
// > 0,表示 q 比较大
}
虽然比较器,可以让你灵活的切换比较属性,但是切换比较属性也是需要改写代码的,所以比较器比较对代码的侵略性强
比较方式 | 特点 |
---|---|
覆写equals方法 | 因为所有类都是继承自 Object 的,所以直接覆写即可,不过只能比较相等与否 |
需比较的类实现了Comparable接口,并重写了compareTo方法 | 需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序 |
创建比较器类,通过比较器对象进行比较(比较器类要实现Comparator接口并重写compare方法) | 需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强 |
例如:以上就是今天要讲的内容,本文分享了java中自定义类的三种比较方法,如果文章中有谬误,欢迎大家批评指正。
路漫漫,不止修身也养性。
文章浏览阅读1.5k次。进阶篇—Soft Actor-Critic (SAC)SAC是一个off-policy + actor critic + maximum entropy的RL算法。比DDPG,SVG等方法稳定并且效果更好。代码参见我的GitHub前言1、on-policy 与 off-policy:on-policy:“边交互边学习” ,每一次参数更新时,都需要与环境交互,因而当遇到复杂任务时,需要的更新步骤更多,增大了复杂度off-policy :“重用过去的经验”,典型的就是经验池策略的方法,比如DQN,DD_soft actor critic 为什么需要两个网络
文章浏览阅读203次。看过一次spring公开课,记录一下bean的循环引用问题。问题:public class IndexService{ @Autowired IndexDao indexDao;}public class IndexDao{ @Autowired IndexService indexService;}以上的实例中IndexService依赖..._spring bean循环引用
文章浏览阅读3.1k次。Docker结合Jenkins部署vue项目接上篇Vue项目没什么好说的,在本地一般使用vue ui启动vue管理的前端,然后在里面进行启动Vue官方说可以不通过ngin来部署,但是如果上生产环境,建议还是要走nginx安装nginx这里安装过程不再赘述,如果不清楚可以参考下面这篇文章https://blog.csdn.net/qq_42815754/article/details/8..._docker jenkins vue-cli
文章浏览阅读1.1k次,点赞2次,收藏15次。Redis—redis结合lnmp架构做mysql的缓存服务器文章目录一 、redis结合lnmp架构做mysql的缓存服务器实现读写分离(一)在server1中配置nginx(二)在server2中配置redis(三)在server3上安装mysql(四)建立php和redis,mysql的连接(五)浏览器访问测试一 、redis结合lnmp架构做mysql的缓存服务器实现读写分离读写分离..._redis+mysql读写分离流程
文章浏览阅读1.1k次。zabbix-agent被动模式变为主动模式配置server2:[root@server2 ~]# vim /etc/zabbix/zabbix_agentd.conf 98 Server=172.25.83.1139 ServerActive=172.25.83.1 #主动模式下,需要配置的。123 # StartAgents=3浏览器:配置——>模板——>Te..._zabbixmoban改为主动模式
文章浏览阅读2.5k次,点赞4次,收藏27次。一、实验内容:1.建立一个空栈2.对已建立的栈进行入栈、出栈、读取栈顶、判空、遍历操作3.用顺序栈实现十进制数转换为二进制数4.用顺序栈实现括号匹配算法二、代码如下:#include<iostream>#include <string.h>using namespace std; //01模板类声明 const int StackSize = 50;template<class DataType>_实现顺序栈的基本操作,进行数制转换和括号匹配的检测;
文章浏览阅读1.1w次,点赞4次,收藏3次。萌新记录一下安装pytest后在pycharm中运行出现的错误,及解决方法问题本人萌新一个,一开始还以为自己pytest和pycharm安装的盘不一样导致的,全部卸了重安,网上的解决方案也试了全部没用,最后找了朋友帮忙。其实只是命名有问题,pytest的文件名称必须为test_.py或_test.py我之前的名称中有空格所以出现问题,修改之后就没有问题了感谢朋友,记录这个小问题..._pycharm控制台执行“pytest” 报错:assert mod not in mods
文章浏览阅读1.5k次,点赞30次,收藏33次。一、Asterisk的下载1、_asterisk搭建voip
文章浏览阅读2.7k次,点赞2次,收藏9次。IP地址的写法: long nErr, nPort; AmsAddr Addr; //ip地址 PAmsAddr pAddr = &Addr; unsigned long lHdlVar; int nIndex; short Data[10]; char szVar []={"MAIN.PLCVar"}; //变量名_vs2017装twincat
文章浏览阅读2k次。#用VirtualBox搭建kali#把启动顺序的网络打勾# 把网卡1作为网络地址转换NAT,可以上网#把网卡2作为仅主机(Host-Only)网络,可以用Xshell等工具远程连接ssh#设置ip地址为动态获取root@kali:~# vi /etc/network/interfaces... #省略内容auto eth0 ..._kali安装metasploit framework
文章浏览阅读245次。Windows Impyla 安装安装各种包报错解决方法安装各种包conda install impylapip install thriftpy2#建议使用此版本,高版本出现数据量大读不出来的问题pip install --no-deps thrift-sasl==0.2.1conda install pure-sasl报错Traceback (most recent call last): File "<input>", line 1, in <module>_conda install thriftpy2
文章浏览阅读3.2k次。vue 使用 element-ui 的 el-autocomplete 组件自定义内容 实现输入框自动提示查 加实时请求。输入的’测试’后台没有相应数据。1 html里<el-autocompletev-model=“state1”popper-class=“my-autocomplete”:fetch-suggestions=“querySearch”placeholder=“请输入内容”@select=“handleSelect”>{{ item.nickname }_vue el autocomplete 实时发送