1

java对象的比较

 2 years ago
source link: https://blog.csdn.net/weixin_49830664/article/details/120817550
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

java对象比较

元素的比较

在java中,基本类型的对象可以直接比较大小。

public static void main(String[] args) {
        int a=12;
        int b=55;
        System.out.println(a > b);
        System.out.println(a == b);
        System.out.println(a<b);

        //字符的比较根据字符所对应ASCII值来比较大小
        char ch1='a';
        char ch2='b';
        char ch3='c';
        System.out.println(ch1>ch2);
        System.out.println(ch1==ch2);
        System.out.println(ch1<ch2);

        boolean b1=true;
        boolean b2=false;
        System.out.println(b1==b2);
        System.out.println(b1!=b2);
    }

在这里插入图片描述
对于String类的比较可以参考我之前写的博客:初识java的String类

对于类的比较如果直接像元素比较一样可能会造成编译错误或者与预期效果的不一样。

class Card{
    public int rank;
    public String suit;
    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
}
public class Main{
public static void main(String[] args) {
        Card c1 = new Card(1, "♠");
        Card c2 = new Card(2, "♠");
        Card c3 = c1;
//        System.out.println(c1>c2);编译报错
        System.out.println(c1==c2);//打印false,因为c1和c2指向的是不同对象
//        System.out.println(c1<c2);编译报错
        System.out.println(c1==c3);//打印false,因为c1和c2指向的是不同对象
    }
}

从此编译结果中我们可以发现,java中引用类型的变量不能直接按照> 或者< 方式进行比较,但确可以使用==符号进行比较?
原因:对于用户自己实现定义的类型,都是默认为Object类,Object类提供了equal方法,此方法的比较规则是:无比较引用变量引用对象的内容,而是直接比较引用变量的地址,因此equal方法一般在使用的时候会被重写

// Object中equal的实现,可以看到:直接比较的是两个引用变量的地址
public boolean equals(Object obj) {
        return (this == obj);
    }

在一些情况下,我们需要比较的是对象的内容,而不是比较对象的地址是否相同,则需要重写比较方法。

重写equals方法

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;
        // o如果是null对象,或者o不是Card的子类
        if (o == null || !(o instanceof Card)) return false;
        Card card = (Card) o;
        return rank == card.rank && Objects.equals(suit, card.suit);
    }
}
Public class Main{
public static void main(String[] args){
		Card c1 = new Card(1, "♠");
        Card c2 = new Card(1, "♠");
        System.out.println(c1.equals(c2));
}
}

其equal方法实现如下:

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

基于Comparble接口类的比较

Comparble是JDK提供的泛型的比较接口类,源码实现具体如下:

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

对于用户自定义类型,如果按照大小与方式进行比较:可以在定义类的时候实现接口Comparable,并在类中重写compareTo方法。

class Card implements Comparable<Card>{
    public int rank;
    public String suit;
    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }

    @Override
    public int compareTo(Card o) {
        return this.rank-o.rank;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || !(o instanceof Card)) return false;
        Card card = (Card) o;
        return rank == card.rank && Objects.equals(suit, card.suit);
    }
}
public class Main {
    public static void main(String[] args) {
        Card p = new Card(1, "♠");
        Card q = new Card(2, "♠");
        Card o = new Card(1, "♠");
        System.out.println(p.compareTo(o)); // == 0,表示牌相等
        System.out.println(p.compareTo(q));// < 0,表示 p 比较小
        System.out.println(q.compareTo(p));// > 0,表示 q 比较大
    }
    }

在这里插入图片描述

基于比较器比较基于比较器比较:Comparator接口

按照比较器方式进行比较,具体步骤如下:

  1. 户自定义比较器类,实现Comparator接口
  2. 覆写Comparator中的compare方法
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 card = (Card) o;
        return rank == card.rank && Objects.equals(suit, card.suit);
    }
}
class CardComparator implements Comparator<Card>{
    @Override
    // 返回值:
    // < 0: 表示 o1 指向的对象小于 o2 指向的对象
    // == 0: 表示 o1 指向的对象等于 o2 指向的对象
    // > 0: 表示 o1 指向的对象等于 o2 指向的对象
    public int compare(Card o1, Card o2) {
       if (o1 == o2) {
            return 0;
        }
        //判断o1是否为空
        if (o1 == null) {
            return -1;
        }
        //判断o2是否为空
        if (o2 == null) {
            return 1;
        }
        return o1.rank - o2.rank;
    }
}
public class Main {
     public static void main(String[] args) {
        Card p = new Card(1, "♠");
        Card q = new Card(2, "♠");
        Card o = new Card(1, "♠");
        //定义比较器对象
        CardComparator cmptor = new CardComparator();
        // 使用比较器对象进行比较
        // == 0,表示牌相等
        System.out.println(cmptor.compare(p, o)); 
        // < 0,表示 p 比较小
        System.out.println(cmptor.compare(p, q)); 
        // > 0,表示 q 比较大
        System.out.println(cmptor.compare(q, p)); 
    }
}

在这里插入图片描述

三种比较方式的对比

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

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK