【Java SE】对象的比较

news2025/1/10 10:26:37

🥰🥰🥰来都来了,不妨点个关注叭!
👉博客主页:欢迎各位大佬!👈

在这里插入图片描述
本期内容满满干货,将会深入介绍对象与对象之间是如何进行比较的,我们知道基本数据类型是可以直接比较大小的,Java中引用类型的变量不能直接按照大于或者小于的方式进行比较,那为什么==可以比较呢?我们一起带着这些问题来了解本期内容

文章目录

  • 1. 等于关系
    • 1.1 ==
    • 1.2 equals方法
    • 1.3 ==和equals方法的区别
  • 2. 大于/小于关系
    • 2.1 实现Comparable接口
    • 2.2 Comparator比较器
    • 2.3 三种重写方法的比较

1. 等于关系

==可以比较引用数据类型的原因
对于用户实现自定义类型,都默认继承Object类,Object类中提供equals方法,==默认情况下调用的就是equals方法,该方法的比较规则是:不是比较引用变量引用对象的内容,而是直接比较引用变量的地址,但有些情况下该种比较就不符合题意,这时就需要重写equals方法,达到我们的目的
Object中equals的实现,可以清楚的看到,直接比较的是两个引用变量的地址

 public boolean equals(Object obj) {
        return (this == obj);
    }

1.1 ==

class Person {
    public String name;
    public String gender;
    public int age;

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

    public String toString() {
        return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }
}


public class Test {
    public static void main(String[] args) {
        //1,==比较基本数据类型
        int a = 10;
        int b = 10;
        System.out.println(a == b);

        //2. ==比较引用数据类型
        Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("泡泡","女",19),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };
        System.out.println(person[0] == person[1]);
        System.out.println(person[0].equals(person[1]));
    }

}

打印结果为:
在这里插入图片描述\

1.2 equals方法

有些情况下,需要比较的是对象中的内容,这时需要重写equals方法,比如上述例子,我们可以看到person[0]与person[1]这两个对象的内容都是一样的,所以我们希望equals方法比较的时候返回的是true

class Person {
    public String name;
    public String gender;
    public int age;

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

    public String toString() {
        return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }

    @Override
    public boolean equals(Object o) {
        //自己和自己比较
        if(this == o) {
            return true;
        }
        //o是null对象或者o不是Person类
        if(o == null || !(o instanceof Person)) {
            return false;
        }

        Person p = (Person)o;
        //基本数据类型如age为int类型可以直接用==比较
        //引用类型最好还是用equals比较
        return name.equals(p.name) && gender.equals(p.gender) && age == p.age;
    }
}


public class Test {
    public static void main(String[] args) {
        //比较引用数据类型
        Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("泡泡","女",19),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };
        System.out.println(person[0] == person[1]);
        System.out.println(person[0].equals(person[1]));
    }

}

打印结果如下:
在这里插入图片描述
因为==实际上还是调用的默认equals方法,对象的地址进行比较,所以打印false,而重写了equals后,再进行比较,我们看到person[0]与person[1]的内容完全一致,所以返回true

equals方法覆写的通用步骤:

  1. 如果指向同一个对象,返回 true
  2. 如果传入的为 null或者传入的对象类型不是该类的,返回false
  3. 按照自己的规则,完成类的实现目标比较
  4. 注意在重写的时候用其他引用类型的比较也需要 equals,例如这里的name,gender的比较

缺点】equals方法只能比较是否相等,不能按照大于、小于的方式进行比较

1.3 ==和equals方法的区别

==
对于基本数据类型,比较的是值
对于引用数据类型,比较的是对象的内存地址

因为Java只有值传递,所以,==不管是比较基本数据类型还是引用数据类型变量, 其本质比较的都是值,只是引用类型变量存的值是对象的地址

equals方法
equals方法比较的也是对象的内存地址,但是可以重写equals,按照自己的比较规则来比较内容是否相等

2. 大于/小于关系

下面我们来看看这个例子,给一个对象数组排序,能否直接用已经有的sort方法呢~

class Person {
    public String name;
    public String gender;
    public int age;

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

    public String toString() {
    return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }

}
public class Test1 {
    public static void main(String[] args) {
        Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("西西","男",33),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };

        Arrays.sort(person);
        System.out.println(Arrays.toString(person));

    }
}

运行结果:运行出错,抛出异常
在这里插入图片描述
答案是显然不行的,因为整数之间是可以直接比较,大小关系明确。但是两个学生对象的大小关系无法确定,需要我们自己额外指定,下面介绍两种方法:

2.1 实现Comparable接口

即Person类实现Comparable接口,并重写该接口的compareTo方法
Comparble是JDK提供的泛型的比较接口类,T代表泛型,实现过程具体如下:

public interface Comparable<T> {
    // 返回值:
    // < 0: 表示this指向的对象小于o指向的对象
    // == 0: 表示this指向的对象等于o指向的对象
    // > 0: 表示this指向的对象大于o指向的对象
    int compareTo(T o);
}

在这里插入图片描述
(一) 以下为使用Comparable接口,按上述例子,年龄进行从大到小排序的代码:

class Person implements Comparable{
    public String name;
    public String gender;
    public int age;

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

    public String toString() {
    return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }

    public int compareTo(Object o) {
        Person p = (Person)o;
        if(this.age > p.age) {
            return -1;
        }else if(this.age < p.age) {
            return 1;
        }else {
            return 0;
        }
        //上述判断可以直接写成
        //return p.age - this.age; 
        //该两个对象比较打印结果为年龄差值
    }

}
public class Test1 {
    public static void main(String[] args) {
        Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("西西","男",33),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };
        //两个对象的比较
        System.out.println(person[0].compareTo(person[1]));
        //对象数组排序
        Arrays.sort(person);
        System.out.println(Arrays.toString(person));

    }
}

运行结果如下:
在这里插入图片描述
解释说明
(1) 表达当前对象大于参数对象
在这里插入图片描述
(2) 在sort方法中会自动调用compareTo方法,compareTo的参数是Object,其实传入的是Person类型的对象,比较当前对象与参数对象的大小关系,可以自己定义比较哪个参数(比如这里按年龄来算的)

1> 如果当前对象应排在参数对象前,返回小于0的数字
2> 如果当前对象应排在参数对象后,返回大于0的数字
3> 如果当前对象与参数对象不分先后,返回0

(3) 如果想让年龄从小到大排序呢~即把大于号改成小于号,小于号改成大于号,记住想让当前对象排在参数对象前,返回值需要小于0

 public int compareTo(Object o) {
        Person p = (Person)o;
        if(this.age < p.age) {
            return -1;
        }else if(this.age > p.age) {
            return 1;
        }else {
            return 0;
        }
    }
 public int compareTo(Object o) {
        Person p = (Person)o;
      	return this.age - p.age;
    }

(二) 以下为使用Comparable接口带泛型的代码:

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

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

    public String toString() {
    return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }

    public int compareTo(Person o) {
        return this.age - o.age;
    }

}
public class Test1 {
    public static void main(String[] args) {
        Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("西西","男",33),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };
        System.out.println(person[0].compareTo(person[1]));
        Arrays.sort(person);
        System.out.println(Arrays.toString(person));

    }
}

打印结果如下:年龄按从小到大排序
在这里插入图片描述
缺点】容易写死,写死就固定下来了~
总结即可以在一个类中实现Comparable接口,并实现该接口的方法comparaTo方法,可按照自己指定规则,进行比较排序

2.2 Comparator比较器

按照比较器比较的方式具体步骤如下:
(1) 用户自定义比较器类,实现Comparator接口

 public interface Comparator<T> {
        // 返回值:
        // < 0: 表示o1指向的对象小于o2指向的对象
        // == 0: 表示o1指向的对象等于o2指向的对象
        // > 0: 表示o1指向的对象大于o2指向的对象
        int compare(T o1,T o2);
    }

在这里插入图片描述
(2) 重写Comparator中的compare方法,上述例子代码如下:

import java.util.Comparator;

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

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

    public String toString() {
        return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }


    @Override
    public int compareTo(Person o) {
        return this.age-o.age;
    }
}

class PersonAgeComparator implements Comparator<Person> {

    @Override
    public int compare(Person o1, Person o2) {
        return o2.compareTo(o1);
    }
}

public class Test2 {

    public static void main(String[] args) {
            Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("西西","男",33),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };

        //定义比较器对象
        PersonAgeComparator tor = new PersonAgeComparator();
        //使用比较器对象进行比较
        System.out.println(tor.compare(person[0],person[1]));
    }
}

运行结果:
在这里插入图片描述注意
(1) Comparator是java.util 包中的泛型接口类,使用时必须导入对应的包,即import java.util.Comparator;
(2) 这里不能直接使用Arrays.sort来排序对象数组,因为没有重写compareTo方法,sort方法中会自动调用compareTo方法

2.3 三种重写方法的比较

在这里插入图片描述💛💛💛本期内容回顾💛💛💛
在这里插入图片描述✨✨✨本期内容到此结束啦~下期再见!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux0.11中MINIX 文件系统

阅读linux 的源码的时候对minix 文件系统有很多的疑惑&#xff0c;根据自己的认识将这些做一个总结。 MINIX 文件系统由六个部分组成&#xff0c;分别是引导块&#xff0c;超级块&#xff0c;i结点位图&#xff0c;逻辑块位图&#xff0c;i结点&#xff0c;数据块。 引导块&am…

面试集中营—Redis架构篇

一、Redis到底是多线程还是单线程 1、redis6.0版本之前的单线程&#xff0c;是指网络请求I/O与数据的读写是由一个线程完成的&#xff1b; 2、redis6.0版本升级成了多线程&#xff0c;指的是在网络请求I/O阶段应用的多线程技术&#xff1b;而键值对的读写还是由单线程完成的。所…

每日Attention学习6——Context Aggregation Module

模块出处 [link] [code] [IJCAI 22] Boundary-Guided Camouflaged Object Detection 模块名称 Context Aggregation Module (CAM) 模块作用 增大感受野&#xff0c;全局特征提取 模块结构 模块代码 import torch import torch.nn as nn import torch.nn.functional as Fcla…

万兆以太网MAC设计(13)主机与FPGA之间进行PING

文章目录 前言&#xff1a;一、ICMP校验和计算二、上板效果1、终端命令行1、wireshark捕捉 前言&#xff1a; 在上板尝试进行PING操作的时候&#xff0c;发现一直是请求超时的情况&#xff0c;结果排查发现是首部校验和没有计算的问题。在UDP层&#xff0c;我们不进行校验和是…

【python】基于岭回归算法对学生成绩进行预测

前言 在数据分析和机器学习领域&#xff0c;回归分析是一种预测连续数值的监督学习技术。当数据特征与目标变量之间存在线性关系时&#xff0c;线性回归模型尤其有用。然而&#xff0c;当特征数量多于样本数量&#xff0c;或者特征之间存在多重共线性时&#xff0c;普通最小二…

jsp 实验16 MVC 表白墙

源代码以及执行结果截图&#xff1a; ExpressWish_Bean.java package web; import java.util.HashMap; import java.util.ArrayList; import java.util.Iterator; public class ExpressWish_Bean { public HashMap<String,ExpressWish> wishList; ArrayList&…

【AI知识】Stable diffusion常用提示词分享

模型&#xff08;Model&#xff09; majicmixRealistic_v7 majicmixRealistic&#xff08;麦橘写实&#xff09;是融合了多种展现日常生活人物形象的写实风格模型&#xff0c;人物的外观更加接近现实生活&#xff0c;对于光影、皮肤、人物动态均有较好的表现&#xff0c;非常…

Java | Leetcode Java题解之第70题爬楼梯

题目&#xff1a; 题解&#xff1a; public class Solution {public int climbStairs(int n) {double sqrt5 Math.sqrt(5);double fibn Math.pow((1 sqrt5) / 2, n 1) - Math.pow((1 - sqrt5) / 2, n 1);return (int) Math.round(fibn / sqrt5);} }

版本控制工具之Git的基础使用教程

Git Git是一个分布式版本控制系统&#xff0c;由Linux之父Linus Torvalds 开发。它既可以用来管理和追踪计算机文件的变化&#xff0c;也是开发者协作编写代码的工具。 本文将介绍 Git 的基础原理、用法、操作等内容。 一、基础概念 1.1 版本控制系统 版本控制系统&#x…

如何区分APP页面是H5还是原生页面?

刚刚接触手机测试的同学&#xff0c;或多或少都有过这样的疑问&#xff1a;APP页面哪些是H5页面&#xff1f;哪些是原生页面?单凭肉眼&#xff0c;简直太难区分了&#xff01;我总结了6个小技巧&#xff0c;希望能帮大家答疑解惑。 1、看断网的情况 断开网络&#xff0c;显示…

推荐 3 个 yyds 的开源项目!

本期推荐开源项目目录&#xff1a; 1. AI 搜索引擎 2. 大模型聊天框架 3. 模仿抖音的移动端短视频 01 AI 搜索引擎 Perplexica 是一个开源的、由 AI 驱动的搜索引擎。它深入互联网寻找答案&#xff0c;不仅搜索网络&#xff0c;还理解您的问题。 Perplexica 受到 Perplexity AI…

今天来聊聊Numpy!

numpy&#xff1f;what&#xff5e;什么是numpy&#xff1f; 小编先暂且不提。 ​ 大家先暂且看看这句话&#xff0c;“你给我翻 译翻译&#xff0c;什么他妈的是他妈的惊喜&#xff1f; 这还用翻译&#xff0c;都说了… 惊喜嘛……”。 惊喜这段出自《让子…

Could not find the Qt platform plugin “dxcb“ in ““、 重点:是dxcb

这个重点就在于是dxcb不是xcb&#xff0c;让我一顿好找。 https://bugs.launchpad.net/ubuntu/source/deepin-qt5dxcb-plugin/bug/1826629 这篇文章描述了应该是deepin系统的一个问题&#xff0c;应该已经修复了不知道为什么我还会遇到。 不过知道是dxcb后直接去qtcreater里的系…

ICode国际青少年编程竞赛- Python-2级训练场-坐标与列表遍历

ICode国际青少年编程竞赛- Python-2级训练场-坐标与列表遍历 1、 for i in range(5):Flyer[i].step(Dev.x -Flyer[i].x) Dev.step(Item.y - Dev.y)2、 for i in range(7):Flyer[i].step(Dev.y - Flyer[i].y) Dev.step(Item[2].x - Dev.x)3、 for i in range(5):Flyer[i].…

基于若依框架搭建网站的开发日志(一):若依框架搭建、启动、部署

RuoYi&#xff08;基于SpringBoot开发的轻量级Java快速开发框架&#xff09; 链接&#xff1a;开源地址 若依是一款开源的基于VueSpringCloud的微服务后台管理系统&#xff08;也有SpringBoot版本&#xff09;&#xff0c;集成了用户管理、权限管理、定时任务、前端表单生成等…

MYSQL8.0.20安装教程

一&#xff1a;下载mysql MySQL :: Download MySQL Installer (Archived Versions) 二&#xff1a;选中server only&#xff0c;点击next 三&#xff1a;点击server 选项&#xff0c;点击Execute 弹窗点击安装 四&#xff1a;安装项为绿色后&#xff0c;点击next 五&#xf…

大数据中的HDFS读写流程(namenode,datanode)

HDFS读写流程 读取流程 1、客户端请求上传文件 2、namenode检查是否存在&#xff0c;可以上传&#xff0c; 3、客户端请求第一个block块上传到datanode 4、namenode返回3个datanode节点&#xff0c;d1,d2,d3 5、客户端请求dn1调用数据&#xff0c;d1收到请求会继续调用d2&#…

使用海外云手机为亚马逊店铺引流

在全球经济一体化的背景下&#xff0c;出海企业与B2B外贸企业愈发重视海外市场的深耕&#xff0c;以扩大市场份额。本文旨在探讨海外云手机在助力亚马逊店铺提升引流效果方面的独特作用与优势。 海外云手机&#xff0c;一种基于云端技术的虚拟手机&#xff0c;能够在单一硬件上…

经典分类网络LeNet5和VGG16项目:实现CIFAR10分类

CIFAR10分类 v1&#xff1a;LeNet5&#xff1a;2cnn3fc 可视化结果 精确率 损失 最佳 v2&#xff1a;LeNet5&#xff1a;3cnn2fc 可视化结果 精确率 损失 最佳 v3&#xff1a;LeNet5&#xff1a;2cnnbnres3fc 可视化结果 精确率 损失 最佳 v4&#xff1a;VG…

web API设计笔记

Hello , 我是小恒。今晚就讲讲我在开发维护API后的经验分享&#xff0c;当然我知识有限&#xff0c;暂时也不会写实际操作。GitHub项目仓库有一堆还在前期开发&#xff0c;我的时间很多时间投在了开源上。 推荐书籍 我认为一个好的 API 设计是面向用户的&#xff0c;充分隐藏底…