文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

java中对象的比较equal、Comparble、Comparator的区别

2024-04-02 19:55

关注

关于对象值相等的比较

三种比较风格

验证== 和 equas在比较风格上的区别

代码实现:按照身份来比较


package java2021_1018;
//写一个辅助的类Card(扑克牌-之前写过)
class Card{
    //按照点数来比较
    public String rank;//点数
    public String suit;//花色
    //提供构造方法
    public Card(String rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
}
public class TestCompare {
    public static void main(String[] args) {
        //写一个类方法,在类方法中构造出这两张牌
        Card a=new Card("3","♠");//第一张牌:a的点数为1,花色为黑桃
        Card b=new Card("3","♠");//第二张牌:b的点数为1,花色为黑桃
        Card c=a;
        //此时已经有了三张牌,但是这三张牌来的方式并不一样,a是通过new一个Card对象,
        //b也是是通过new一个Card对象,而c是相当于和直接a指向同一个card对象

        //《使用 == 等号,进行比较》
        System.out.println("==============使用 == 等号,进行比较的结果==============");
        System.out.println(a == c);//结果为true
        System.out.println(a == b);//结果为false
        //第二个结果为true是因为a和b分别new了两个对象,这两个对象的身份是不相等的,所以执行 == 比较就是false的情况
        //《使用equals进行比较》
        System.out.println("==============使用equals进行比较的结果==============");
        System.out.println(a.equals(c));//结果为true
        System.out.println(a.equals(b));//结果为false
        
    }
}

打印结果:

image-20211021111013802

覆写基类的equal

给equals加上一个重写,使它变成比较值(内容)的方法

代码实现:按照值来比较


package java2021_1018;

class Card{
    public String rank;//点数
    public String suit;//花色
    public Card(String rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
    
    @Override
    public boolean equals(Object obj) {//参数:obj,类型:Object
        //按照值来比较this和obj
        //1.考虑自己和自己比较的情况
        if(this == obj){ //先看看比较的这两个对象是不是同一个对象,如果是,就返回true
            return true;//因为两个对象(引用)如果身份相同的话,那么值也肯定是相同的
        }
        //2.考虑obj为null的情况,认为结果为false, 避免出现空引用异常。 因为this是不可能为null的,如果它是null,就无法调用equals方法了
        //所以如果obj为null,this不为null,那就返回false,有了这样的一个条件判断,就可以保证在后面这个obj == null逻辑执行的时候,就不会出现空引用异常了
        if(obj == null){
            return false;
        }
        //3、考虑类型不匹配的情况,即考虑obj这个类型是不是当前的Card类型,如果equals里传了一个其他参数类型进来,此时两个类型不同是无法比较相等的,所以需要判断一下哦
        if (!(obj instanceof Card)){//如果obj这个参数不是Card这个类型的话,就返回false
            return false;
            //同时类型转换也带有类型转换失败的风险,所以在使用之前也要先确认好类型是否匹配
        }
        //4.真正的比较内容
        Card other = (Card)obj;//此时的参数类型是Object类型,所以需要先对obj进行一个类型的强转,并赋值给一个变量other
        //再去比较判断 点数或花色 或 点数和花色 是否相等
        return this.rank.equals(other.rank) && this.suit.equals(other.suit);
    }
    //这相当于是一个标准的重写equals的一个模板,以后再写其他的一些自己的比较方法的时候也要按照这种思路一步步往下考虑
}
public class TestCompare1 {
    public static void main(String[] args) {
        Card a=new Card("3","♠");//第一张牌:a的点数为1,花色为黑桃
        Card b=new Card("3","♠");//第二张牌:b的点数为1,花色为黑桃
        Card c=a;      
        System.out.println("==============使用 == 等号,进行比较的结果==============");
        System.out.println(a == c);//结果为true
        System.out.println(a == b);//结果为true,因为a和b分别new了两个对象,这两个对象的身份是不相等的,所以执行 == 比较就是false的情况
        System.out.println("==============使用equals进行比较的结果==============");        
        System.out.println(a.equals(c));//结果为true
        System.out.println(a.equals(b));//结果为true      
    }
}

打印结果:

image-20211021115311130

注意:一般覆写 equals 的套路就是上面演示的

在实现equals中所需考虑的几个步骤,及涉及到的细节,在实现其他类的equals时也基本上就是代码中所考虑的这几个操作(套路)。

关于对象值大于、等于、小于的比较–基于自然顺序(按照<小于号的形式)

基于Comparble接口类的比较

Comparble这个接口相当于就是重新定义小于这个操作

下面通过代码来体会一下Comparble这个接口的作用,还是基于Card这个类来进行比较,如果想要使用Comparble这个接口的话,就需要让Card实现一个Comparble,由于Comparble是一个带泛型的接口,于是就需要给它写一个泛型参数,但也不是非写不可。

image-20211021144045443

代码实现:基于Comparble接口类的比较


package java2021_1018;

class Card  implements Comparable<Card>{//实现一个 Comparable的接口,由于Comparble是一个带泛型的接口,于是就需要给它写一个泛型参数
    //按照点数来比较
    public String rank;//点数
    public String suit;//花色
    //提供构造方法
    public Card(String rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
//重写compareTo方法
    @Override
    public int compareTo(Card o) {
        if(o == null){//如果o传过来的参数是一个空引用,就认为this比null要大
            //一般也认为null的值比较小
            return 1;
        }
        //点数的取值:是2~10的一系列整数,和J  Q  K  A;如果点数值在2~10的话,直接返回成整数,如果点数值是J  Q  K  A的话,就手动把这四个点数设置成11,12,13,14然后把值算出来之后再去分别比较大小
        int rank1 = this.getValue();//this的值
        int rank2 = o.getValue();//o的值
        return rank1-rank2;//返回二者的差值,返回的值参考compareTo的语法规则
    }
//写一个获取值的方法,
    private int getValue() {
        //通过这个方法把String 类型的rank(J  Q  K  A)变成数字点数11,12,13,14
        int value = 0;
        if("J".equals(rank)){
            value = 11;
        }else if("Q".equals(rank)){
            value = 12;
        }else if("K".equals(rank)){
            value = 13;
        }else if ("A".equals(rank)){
            value = 14;
        }else {
            value = Integer.parseInt(rank);//把字符串转成数字
            //单独处理J  Q  K  A,然后其他的2~10直接使用Integer.parseInt,把字符串转换成整数。
        }
        return value;
    }

public class TestCompare1 {
    public static void main(String[] args) {
        //写一个类方法,在类方法中构造出这两张牌
        Card a=new Card("3","♠");//第一张牌:a的点数为1,花色为黑桃
        Card b=new Card("2","♦");//第二张牌:b的点数为1,花色为黑桃
        Card c=a;
        //调用compareTo比较方法
        System.out.println(a.compareTo(b));
        System.out.println(a.compareTo(c));
    }
}

compareTo方法的语法规则

不同的点数比较后所打印出来的结果如下图:

image-20211021162303939

关于对象值大于、等于、小于的比较-- 基于比较器比较

基于Comparator接口类的比较

Comparator也是一个接口,想要使用它也要让你的类去实现这个接口,同时去重写一个compare方法,但是不同的是compare方法里面有两个参数,

Comparable和Comparator,他俩的区别在于Comparator定义出的比较器和原来的类不是一个耦合在一起的关系

即使用Comparable的时候,你必须让要比较的类实现Comparable接口,换句话说,就是需要修改这个类的代码,比如刚才待比较类是Card,如果要是用Comparable这种实现方式的时候,必须得修改Card的源码。

而使用Comparator的时候,你是重新创建一个新的类实现Comparator接口,不需要修改待比较类的代码,比如刚才待比较类是Card,如果要是用Comparator这种实现方式的时候,就不用改Card的源码

所以说使用Comparable这种实现方式的时候,它的耦合性就更强一些,但这是我们不愿意看到的。

代码实现:基于Comparator接口类的比较


package java2021_1018;

import java.util.Comparator;

//写一个辅助的类Card(扑克牌-之前写过)
class Card {
    //按照点数来比较
    public String rank;//点数
    public String suit;//花色
    //提供构造方法

    public Card(String rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
//写一个获取值的方法,
   public int getValue() {
        //通过这个方法把String 类型的rank(J  Q  K  A)变成数字点数11,12,13,14
        int value = 0;
        if("J".equals(rank)){
            value = 11;
        }else if("Q".equals(rank)){
            value = 12;
        }else if("K".equals(rank)){
            value = 13;
        }else if ("A".equals(rank)){
            value = 14;
        }else {
            value = Integer.parseInt(rank);//把字符串转成数字
            //单独处理J  Q  K  A,然后其他的2~10直接使用Integer.parseInt,把字符串转换成整数。
        }
        return value;
    }
}z
//写一个CardComparator类
class CatdComparator implements Comparator<Card>{//这里指定泛型参数就是针对谁比较就写谁
//实现一个compare方法
    @Override
    public int compare(Card o1, Card o2) {//compare方法里面有两个参数,类型都是Card类型
        //判断特殊情况
        if(o1 == o2){//如果o1 和 o2身份相等
            return 0;
        }
        //判断o1 、 o2是不是null的情况
        if(o1 == null){
            return -1;
        }
        if(o2 == null){
            return 1;
        }
        //比较值
        int value1 = o1.getValue();
        int value2 = o2.getValue();
        return value1-value2;
    }
}
public class TestCompare1 {
    public static void main(String[] args) {
        //写一个类方法,在类方法中构造出这两张牌
        Card a=new Card("3","♠");//第一张牌:a的点数为1,花色为黑桃
        Card b=new Card("K","♠");//第二张牌:b的点数为1,花色为黑桃
        Card c=a;
 //Comparator的使用:先创建一个Comparator的实例
        CatdComparator comparator = new CatdComparator();
        System.out.println(comparator.compare(a,b));
    }
}

疑问:为什么有了Comparable还需要有一个Comparator呢?

1、因为Comparable使用的时候必须要修改待比较类的代码,实际开发中不是所有的类都能修改源码,(如果这个类是库或者是其他组的人提供的此时就不能随便改人家的代码,只能改自己的代码)。

2、Comparable只能定义一种比较规则,Comparator可以定义多种比较规则(即可以实现多个Comparator类)。如:代码中的CardComparator类,定义多份之后就可以有多种不同的比较规则了,然后就可以在不同的比较规则里面分别针对当前的场景来自定制按照什么样的方式来比较了。

三种比较方式对比

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

到此这篇关于java中对象的比较equal、Comparble、Comparator的区别的文章就介绍到这了,更多相关java equal、Comparble、Comparator内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯