对象的比较 Java

什么是比较?

在计算机领域中,比较分为两种:

  • 身份的比较
  • 值的比较

而在Java中主要有三种比较方式:

  • Object.equals
  • Comparable
  • Comparator

下面我们逐个总结:

1. == VS equals

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

覆写前

public class Card {
    public String rank;
    public String suit;

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

    public static void main(String[] args) {
        Card card1 = new Card("A", "♥️");
        Card card2 = new Card("K", "♦️");
        Card c = card1;

        card1.equals(card2);//false 因为不覆写 equals,默认的 equals逻辑就是引用比较
        card1.equals(c);//true 因为不覆写 equals,默认的 equals逻辑就是引用比较
    }

}

覆写后

public class Card {
    public int rank;
    public String suit;

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

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || !(o instanceof Card)) {
            return false;
        }
        Card c = (Card)o;
        return this.rank == c.rank
                && this.suit.equals(c.suit) ;
    }

    public static void main(String[] args) {
        Card card1 = new Card(5, "♦️");
        Card card2 = new Card(5, "♥️");
        Card c = card1;

        card1.equals(card2); // true
        card1.equals(c);   //true
    }
}

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

2. Comparable

我们在使用 Comparable 接口的时候要实现它的 compareTo 方法
compareTo 的返回值

  • // < 0: 表示 this 指向的对象小于 o2 指向的对象
  • // == 0: 表示 this 指向的对象等于 o2指向的对象
  • // > 0: 表示 this 指向的对象等于 o2 指向的对象
public class Card implements Comparable<Card>{
    public int rank;
    public String suit;

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

    //我们人为 null 是最小的
    @Override
    public int compareTo(Card o) {
        if (o == null) {
            return 1;
        }
        return this.rank - o.rank;
    }

    public static void main(String[] args) {
        Card card1 = new Card(1, "♦️");
        Card card2 = new Card(2, "♥️");
        Card card3 = new Card(1, "♦️");

        card1.compareTo(card2); // < 0 表示 card1 比较小
        card1.compareTo(card3); // == 0 表示 相等
        card2.compareTo(card3); // > 0 表示 card2 比较大
    }
}

3. Comparator

我们在使用 Comparator 接口的时候要先在主类实现 Comparable接口,和comparaTo 方法。然后在创建一个类来实现 Comparator 接口,再实现compare 方法。
compare 的返回值

  • // < 0: 表示 o1 指向的对象小于 o2 指向的对象
  • // == 0: 表示 o1 指向的对象等于 o2指向的对象
  • // > 0: 表示 o1 指向的对象等于 o2 指向的对象
import java.util.Comparator;

public class Card implements Comparable<Card>{
    public int rank;
    public String suit;

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

    //我们人为 null 是最小的
    @Override
    public int compareTo(Card o) {
        if (o == null) {
            return 1;
        }
        return this.rank - o.rank;
    }




    public static void main(String[] args) {
        Card card1 = new Card(1, "♦️");
        Card card2 = new Card(2, "♥️");
        Card card3 = new Card(1, "♦️");

        Comparator<Card> comparator = new CardComparator();
        comparator.compare(card1, card2); // = 0,表示 牌大小相等
        comparator.compare(card1, card3); // < 0,表示 card1 比较小
        comparator.compare(card2, card3); // > 0,表示 card1 比较大

    }
}
class CardComparator implements Comparator<Card> {
    @Override
    public int compare(Card o1, Card o2) {
        if (o1 == o2) {
            return 0;
        }
        if (o1 == null) {
            // o2 一定不是 null
            return -1;
        }
        if (o2 == null) {
            return 1;
        }
        return o1.rank - o2.rank;
    }
}

三种比较方法的比较

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

和Java集合框架的配合

  1. 使用 contains 类似的方法,内部基本在调用元素的 equals 方法,所以要求元素覆写过 equals 方法
  2. 使用 HashMap,key 的比较内部会调用 equals 方法,所以要求元素覆写过 equals 方法
  3. 使用排序相关方法,内部需要进行比较,所以或者选择实现Comparable 或者传入一个 Comparator
  4. 使用 TreeMap,key 需要进行大小比较,所以或者选择实现 Comparable 或者传入一个 Comparator
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值