Java 基本类型比较 + 自定义类比较 + 对象的三种比较方法重写equals方法 /重写compareTo方法 /使用比较器_java重写compareto方法-程序员宅基地

技术标签: jvm  java  Java数据结构  开发语言  


前言

本人是一个刚刚上路的IT新兵,菜鸟!分享一点自己的见解,如果有错误的地方欢迎各位大佬莅临指导,如果这篇文章可以帮助到你,劳请大家点赞转发支持一下!

上一篇文章,讲解了优先级队列,从这里开始就对插入的数据有要求了,那就是插入的数据必须可以比较,有优先级之分。并且以后要用到比较的地方也越来越多,所以今天就来讲一讲java对象的比较


一、PriorityQueue中插入对象

优先级队列在插入元素时有个要求:插入的元素不能是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是没有办法直接进行比较的,因此抛出异常。


二、数据的比较

1.基本类型的比较

在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);

    }

2.自定义类的比较

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指向的是同一个对象
        
    }
  • Java中引用类型的变量不能直接按照 > 或者 < 方式进行比较。

那为什么 == 可以比较呢?
对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equal方法,而==默认情况下调用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地
址。
在这里插入图片描述
Object中equal的实现,是直接比较的是两个引用变量是否指向同一个地址


3.对象的比较

1.覆写基类的equals

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只能按照相等进行比较,不能按照大于、小于的方式进行比较。


2.基于Comparble接口类的比较

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中的接口类,可以直接使用。

用这种写法呢,就将比较方式写死了,就不能再通过其他属性来比较了,侵略性强。


3.基于比较器比较

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方法。

  • 划重点,所以写比较器要实现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中自定义类的三种比较方法,如果文章中有谬误,欢迎大家批评指正。

路漫漫,不止修身也养性。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/The_emperoor_man/article/details/129226089

智能推荐

进阶篇---Soft Actor-Critic (SAC)_soft actor critic 为什么需要两个网络-程序员宅基地

文章浏览阅读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 为什么需要两个网络

spring bean的循环引用-程序员宅基地

文章浏览阅读203次。看过一次spring公开课,记录一下bean的循环引用问题。问题:public class IndexService{  @Autowired  IndexDao indexDao;}public class IndexDao{  @Autowired  IndexService indexService;}以上的实例中IndexService依赖..._spring bean循环引用

Docker结合Jenkins部署vue项目_docker jenkins vue-cli-程序员宅基地

文章浏览阅读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

MySQL与Redis数据库结合(一)——lnmp+redis+mysql实现读写分离_redis+mysql读写分离流程-程序员宅基地

文章浏览阅读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读写分离流程

zabbix-agent被动模式变为主动模式_zabbixmoban改为主动模式-程序员宅基地

文章浏览阅读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改为主动模式

栈的基本操作,顺序栈的入栈、出栈、读取栈顶、判空、遍历操作,用顺序栈实现十进制数转换为二进制数,以及括号匹配算法(c++ 数据结构 实验三)_实现顺序栈的基本操作,进行数制转换和括号匹配的检测;-程序员宅基地

文章浏览阅读2.5k次,点赞4次,收藏27次。一、实验内容:1.建立一个空栈2.对已建立的栈进行入栈、出栈、读取栈顶、判空、遍历操作3.用顺序栈实现十进制数转换为二进制数4.用顺序栈实现括号匹配算法二、代码如下:#include<iostream>#include <string.h>using namespace std; //01模板类声明 const int StackSize = 50;template<class DataType>_实现顺序栈的基本操作,进行数制转换和括号匹配的检测;

随便推点

在pycharm中运行pytest报错ModuleNotFoundError: No module named 'pytest'_pycharm控制台执行“pytest” 报错:assert mod not in mods-程序员宅基地

文章浏览阅读1.1w次,点赞4次,收藏3次。萌新记录一下安装pytest后在pycharm中运行出现的错误,及解决方法问题本人萌新一个,一开始还以为自己pytest和pycharm安装的盘不一样导致的,全部卸了重安,网上的解决方案也试了全部没用,最后找了朋友帮忙。其实只是命名有问题,pytest的文件名称必须为test_.py或_test.py我之前的名称中有空格所以出现问题,修改之后就没有问题了感谢朋友,记录这个小问题..._pycharm控制台执行“pytest” 报错:assert mod not in mods

Ubuntu20.04下载Asterisk源码并配置搭建VoIP(一条龙服务,从无到有的搭建)_asterisk搭建voip-程序员宅基地

文章浏览阅读1.5k次,点赞30次,收藏33次。一、Asterisk的下载1、_asterisk搭建voip

TwinCAT数据读写_vs2017装twincat-程序员宅基地

文章浏览阅读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

Kali搭建metasploit-framework做渗透测试_kali安装metasploit framework-程序员宅基地

文章浏览阅读2k次。#用VirtualBox搭建kali#把启动顺序的网络打勾# 把网卡1作为网络地址转换NAT,可以上网#把网卡2作为仅主机(Host-Only)网络,可以用Xshell等工具远程连接ssh#设置ip地址为动态获取root@kali:~# vi /etc/network/interfaces... #省略内容auto eth0 ..._kali安装metasploit framework

Windows impyla 踩坑_conda install thriftpy2-程序员宅基地

文章浏览阅读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

vue 使用 element-ui 的 el-autocomplete 组件自定义内容 实现输入框自动提示查 加实时请求。_vue el autocomplete 实时发送-程序员宅基地

文章浏览阅读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 实时发送

推荐文章

热门文章

相关标签