java对象的比较

一、基本类型的比较

在Java中,基本类型的对象可以直接比较大小。
(<,>,>=,<=,==,!=)

==运算符比较:

基本数据类型,比较值是否相同

引用类型,比较引用变量的首地址是否相同

二、equals

equals 有两种判断方式,但是都是建立在引用类型上的比较
1.当我们的子类没有重写equals 时,我们调用的时Object 的equals方法,只能判断两个引用类型的地址是否相同;
2.当我们的子类重写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) {
// 自己和自己比较,如果相等返回true
        if (this == o) {
            return true;
        }
//o如果是null对象,或者o不是Card的子类
        if (o == null || !(o instanceof Card)) {
            return false;
        }
//注意基本类型可以直接比较,但引用类型最好调用其equal方法
        Card c = (Card) o;
        return rank == c.rank
                && suit.equals(c.suit);     //这里是直接比较数值的大小
    }
}

注意: 一般覆写 equals 的套路就是上面演示的
1. 如果指向同一个对象,返回 true
2. 如果传入的为 null,返回 false
3. 如果传入的对象类型不是 Card,返回 false
4. 按照类的实现目标完成比较,例如这里只要花色和数值一样,就认为是相同的牌
5. 注意下调用其他引用类型的比较也需要 equals,例如这里的 suit 的比较覆写基类equal的方式虽然可以比较,但缺陷是:equal只能按照相等进行比较,不能按照大于、小于的方式进行比较。

equalsgnoreCase  比较的是内容并且忽略大小写。

三、Comparble比较器

Comparable接口

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

public interface Comparable {

public int compareTo(T o);

}

该接口只存在一个public int compareTo(T o);方法,该方法表示所在的对象和o对象进行比较,返回值分三种:
1: 表示当前对象大于o对象
0: 表示当前对象等于o对象
-1: 表示当前对象小于o对象

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

举个栗子:

需求: 在优先级队列中存储对象学生,每个学生有idnameage三个属性,并且使优先级队列每次按照学生的id从小到大取出。

代码示例:
Student类: 当前类实现了Comparable接口,即当前类提供了默认的比较方法。

实现接口,创建自定义类
public class Student implements Comparable{
    private int id;
    private String name;
    private int age;
    
    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
//重写compareTo方法
    @Override
    public int compareTo(Object o) {
        Student o1 = (Student)o;
        return this.id - o1.id;
    }
}

Comparator比较器

如果使优先级队列按照学生id从大到小取出呢?我们很快就会想到修改Student类的compareTo方法,使return o1.id - this.id;,这样当然可以实现我们的新需求。但是有很多时候类的compareTo方法是不能修改的,比如JDK给我们提供的源代码,在不修改compareTo方法的前提下实现需求,只能用Comparator比较器了。

Comparator接口

public interface Comparator {

int compare(T o1, T o2);

}

该接口中提供了int compare(T o1, T o2)方法,该方法需要参数是两个待比较的对象
返回结果是int类型:
1: 表示o1对象大于o2对象
0: 表示o1对象等于o2对象
-1: 表名o1对象小于o2对象

覆写Comparator中的compare方法

import java.util.Comparator;
class Card {
public int rank; // 数值
public String suit; // 花色
public Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
}
class CardComparator implements Comparator {
// 根据数值比较,不管花色
// 这里我们认为 null 是最小的
@Override
public int compare(Card o1, Card o2) {
if (o1 == o2) {
return 0;
} if
(o1 == null) {
return -1;
}
if (o2 == null) {
return 1;
} 
return o1.rank - o2.rank;
}
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();
// 使用比较器对象进行比较
System.out.println(cmptor.compare(p, o)); // == 0,表示牌相等
System.out.println(cmptor.compare(p, q)); // < 0,表示 p 比较小
System.out.println(cmptor.compare(q, p)); // > 0,表示 q 比较大
}
}

注意:Comparator是java.util 包中的泛型接口类,使用时必须导入对应的包。

三种方式的比较

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

你可能感兴趣的:(java基础,java,算法,c#)