对象的比较 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
发布了140 篇原创文章 · 获赞 16 · 访问量 8654

猜你喜欢

转载自blog.csdn.net/Huwence/article/details/103129564
今日推荐