你了解如何比较两个对象吗

一,关于对象值相等的比较

1, == VS equals

  • p == q 表示的是 p 和 q 两个引用指向同一个对象
  • p.equals(q) 表示 p 指向的对象 和 q 指向的对象是否是值语义相等的

2,代码示例

覆写equals前

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 p = new Card("3","♠");
        Card q = new Card("3","♠");
        Card o = p;
        System.out.println(o == p);  //测试 == 比较身份
        System.out.println(p == q);
        System.out.println("===============================");
        System.out.println(p.equals(o));  //测试比较内容
        System.out.println(p.equals(q));  //没有重写的话,使用的是Object中的原始的equals方法,相当于依旧比较的是身份
    }
}

运行结果:
在这里插入图片描述
覆写equals后

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) {
        //按照值比较this和obj
        // 1,自己与自己比较
        if(this == obj){
            return true;
        }
        //2,obj为null的情况
        if(obj == null){
            return false;
        }
        //3,obj类型不是当前card类型
        if(! (obj instanceof Card) ){
            return false;
        }
        //4,真正的比较内容
        Card other = (Card)obj;
        return this.rank.equals(other.rank) && this.suit.equals(other.suit);

    }

}
public class TestCompare {
    public static void main(String[] args) {
        Card p = new Card("3","♠");
        Card q = new Card("3","♠");
        Card o = p;
        System.out.println(o == p);  //测试 == 比较身份
        System.out.println(p == q);
        System.out.println("===============================");
        System.out.println(p.equals(o));  //测试比较内容
        System.out.println(p.equals(q));  //重写后
    }
}

在这里插入图片描述
注意: 一般覆写 equals 的套路就是上面演示的

  1. 如果指向同一个对象,返回 true
  2. 如果传入的为 null,返回 false
  3. 如果传入的对象类型不是 Card,返回 false
  4. 按照类的实现目标完成比较,例如这里只要花色和数值一样,就认为是相同的牌
  5. 注意下调用其他引用类型的比较也需要 equals,例如这里的 suit 的比较

二,关于对象值大于、等于、小于的比较-基于自然顺序

1,认识 Comparable

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

2,代码示例

package java15_20200510;

class Card implements Comparable<Card>{
    public String rank;  //点数
    public String suit;  //花色

    public Card(String rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
    @Override
    public int compareTo( Card o) {
        //如果this比o小,返回一个小于0的整数
        //如果this比o大,返回一个大于0的整数
        //如果this == o,返回0
        if(o == null){
            //一般我们就认为this比o大,null比较小
            return  1;
        }
        //点数取值2-10. JQKA
        int rank1 = this.getValue();
        int rank2 = o.getValue();
        return rank1-rank2;
    }
    public int getValue(){
        //通过这个方法把String类型变为整数点数
        int value = 0;
        if("j".equals(rank)){
            value =  10;
        } else if("Q".equals(rank)){
            value = 11;
        } else if("k".equals(rank)){
            value = 12;
        } else if("A".equals(rank)){
            value = 14;
        } else {
            value = Integer.parseInt(rank);
        }
        return value;
    }
}
public class TestCompare {
    public static void main(String[] args) {
        Card p = new Card("3","♠");
        Card q = new Card("3","♠");
        Card o = p;
        System.out.println(p.compareTo(null));
        System.out.println(p.compareTo(q));
    }
}

运行结果:
在这里插入图片描述

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

1, 认识 Comparator

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

2,代码示例

import java.util.Comparator;

class Card {
    public String rank;  //点数
    public String suit;  //花色

    public Card(String rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }

    public int getValue(){
        //通过这个方法把String类型变为整数点数
        int value = 0;
        if("j".equals(rank)){
            value =  10;
        } else if("Q".equals(rank)){
            value = 11;
        } else if("k".equals(rank)){
            value = 12;
        } else if("A".equals(rank)){
            value = 14;
        } else {
            value = Integer.parseInt(rank);
        }
        return value;
    }
}
class CarComparator implements Comparator<Card> {
    @Override
    public int compare(Card o1, Card o2) {
        if(o1 == o2){
            return 0;
        }
        if(o1 == null){
            return -1;
        }
        if(o2 == null){
            return 1;
        }
        int result1 = o1.getValue();
        int result2 = o2.getValue();
        return result1-result2;
    }
}
public class TestCompare {
    public static void main(String[] args) {
        Card p = new Card("3","♠");
        Card q = new Card("3","♠");
        Card o = p;
        CarComparator comparator = new CarComparator();
        System.out.println(comparator.compare(p,q));
        System.out.println(comparator.compare(p,null));
        System.out.println(comparator.compare(null,q));
    }
}

运行结果:
在这里插入图片描述

四,比较

在这里插入图片描述

五,和 java 集合框架的配合

  1. 使用 contains 类似的方法,内部基本在调用元素的 equals 方法,所以要求元素覆写过 equals 方法
  2. 使用 HashMap,key 的比较内部会调用 equals 方法,所以要求元素覆写过 equals 方法
  3. 使用排序相关方法,内部需要进行比较,所以或者选择实现 Comparable 或者传入一个 Comparator
  4. 使用 TreeMap,key 需要进行大小比较,所以或者选择实现 Comparable 或者传入一个 Comparator
  5. 其他规则以此类推

六,注意事项

1,使用Comparable接口的时候,最好指定泛型参数.编译器自动的完成类型校验工作.如果不写泛型参数,默认的compareTo方法的参数类型就是Object类型.需要程序猿手动进行类型转换.
2,使用Comparable的时候,你必须让要比较的类实现Comparable接口. (需要修改这个类的代码)
3,使用Comparator的时候,你是重新创建一个新的类实现Comparator接口,不需要修改待比较类的代码

问题:为啥有了Comparable还需要有一个Comparato呢?
1,使用Comparator的时候必须要修改带比较类的代码,实际开发中不是所有的类都能修改源码(这个类是库或者其它组提供的)
2.Comparable只能定义一种比较规则,Comparator可以定义多种比较规则

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值