Java中对象的比较(equals、Comparable、Comparator)

文章目录

  • 一、PriorityQueue中插入对象
  • 二、元素的比较
    • 2.1、基本类型的比较
    • 2.2、对象比较的问题
  • 三、对象的比较
    • 3.1、覆写基类的equals
    • 3.2、基于Comparable接口类的比较
    • 3.3、基于比较器比较
    • 3.4、三种方式对比

一、PriorityQueue中插入对象

前篇我们讲解了优先级队列,大家应该还记得,其内部是按照小根堆的方式实现的,插入元素的前提是不为null或者元素必须能够比较,为了方便我们当时插入的为Integer类型的元素,那如果我们插入自定义类型对象呢?

class Card {
    public int rank; // 数值
    public String suit; // 花色
    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
}
public class TestPriorityQueue {
    public static void TestPriorityQueue()
    {
        PriorityQueue<Card> p = new PriorityQueue<>();
        p.offer(new Card(1, "♠"));
        p.offer(new Card(2, "♠"));
    }
    public static void main(String[] args) {
        TestPriorityQueue();
    }
}

如上代码,优先级队列的底层使用堆,向堆中插入元素时,为了满足堆的性质,必须要进行元素的比较,而此时Card为自定义数据类型,是没有办法直接进行比较的,因此抛出异常。 

 那么怎么做才能比较自定义数据类型呢?我们往下看:

二、元素的比较

2.1、基本类型的比较

在Java中,基本类型的元素是可以直接比较大小的,如下(注释为输出结果): 

2.2、对象比较的问题

class Card {
    public int rank; // 数值
    public String suit; // 花色
    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
}

public class text {
    public static void main(String[] args) {
        Card c1 = new Card(1, "♠");
        Card c2 = new Card(1, "♠");
        Card c3 = c1;
    }
}

1、c1==c2

        c1,c2分别new了一个Card类型的对象,分别指向不同的对象,其地址也不同,所以会打印false

2、c1.equals(c2):

        我们的Card类默认继承Object类的,Object类中实现了equals方法,所以我们能够直接调用,但为什么是false呢?我们点进源码看到,其返回的就是c1==c2

3、c1==c3:

        c1c3指向同一个对象,过其返回true 

那么当我们用><符号进行比较时,会发生什么?

我们可看出Java中引用类型的变量不能直接按照 > 或者 < 方式进行比较,为什么可以使用==进行比较呢?

因为:

        对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equal方法,而==默认情况下调 用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地址

三、对象的比较

3.1、覆写基类的equals

那么,我们在Card中重写Object类中的equals方法

public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Card card = (Card) o;
        return rank == card.rank && Objects.equals(suit, card.suit);
    }

 我们发现c1.equals(c2)就返回true

重写的equals

1. 如果指向同一个对象,返回 true

2. 如果传入的为 null,返回 false

3. 如果传入的对象类型不是 Card,返回 false

4. 按照类的实现目标完成比较,例如这里只要花色和数值一样,就认为是相同的牌

5. 注意下调用其他引用类型的比较也需要 equals,例如这里的 suit 的比较 

缺陷:equal 只能按照相等进行比较,不能按照大于、小于的方式进行比较 

3.2、基于Comparable接口类的比较

对于用户自定义的数据类型,如果想按照大小与方式进行比较时:在定义类时,实现Comparble接口即可,然后在类中重写compareTo方法。

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;
    }
}

我们就按照期待的结果(按照数值比较)成功比较出c1和c2的数值大小关系 :

注意:Compareblejava.lang中的接口类,可以直接使用。 

3.3、基于比较器比较

上述我们可以比较自定义类型的数值,那么花色的比较要实现Comparator接口,重写compare方法:

class suitComparator implements Comparator<Card> {
    @Override
    public int compare(Card o1, Card o2) {
        return o1.suit.compareTo(o2.suit);
    }
}
public static void main(String[] args) {
        Card c1=new Card(12,"♥");
        Card c2=new Card(13,"♠");
        suitComparator com=new suitComparator();
        if(com.compare(c1,c2)>0){
            System.out.println("c1 > c2");
        }else{
            System.out.println("c1 < c2");
        }

        if(com.compare(c1,c3)>0){
            System.out.println("c1 > c3");
        }else{
            System.out.println("c1 < c3");
        }

        if(com.compare(c2,c3)>0){
            System.out.println("c2 > c3");
        }else{
            System.out.println("c2 < c3");
        }
    }
//结果:
//    c1 > c2
//    c1 > c3
//    c2 < c3

我们就成功比较出Card类对象的花色大小。 

3.4、三种方式对比

        Comparable是Java中一个接口,它用于实现对象的比较。如果一个类实现了Comparable接口,就意味着该类的对象是可以排序的。Comparable接口中只有一个方法compareTo(Object o),该方法用于比较对象的大小关系。

        equals是Java中一个方法,用于比较两个对象是否相等。equals方法实际上是用来比较两个对象的内容是否相等,而不是比较对象的引用是否相等。equals方法通常会被重写,以实现自定义的相等逻辑。

        Comparator是Java中一个接口,它可以用于实现两个对象的比较。Comparator接口中有一个方法compare(Object o1, Object o2),该方法用于比较o1和o2的大小关系。Comparator接口可以用于对任意的对象进行排序,而不需要修改对象的定义,因此它具有更大的灵活性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值