【Java SE】对象的比较

发布于:2024-05-10 ⋅ 阅读:(24) ⋅ 点赞:(0)

🥰🥰🥰来都来了,不妨点个关注叭!
👉博客主页:欢迎各位大佬!👈

在这里插入图片描述
本期内容满满干货,将会深入介绍对象与对象之间是如何进行比较的,我们知道基本数据类型是可以直接比较大小的,Java中引用类型的变量不能直接按照大于或者小于的方式进行比较,那为什么==可以比较呢?我们一起带着这些问题来了解本期内容

1. 等于关系

==可以比较引用数据类型的原因
对于用户实现自定义类型,都默认继承Object类,Object类中提供equals方法,==默认情况下调用的就是equals方法,该方法的比较规则是:不是比较引用变量引用对象的内容,而是直接比较引用变量的地址,但有些情况下该种比较就不符合题意,这时就需要重写equals方法,达到我们的目的
Object中equals的实现,可以清楚的看到,直接比较的是两个引用变量的地址

 public boolean equals(Object obj) {
        return (this == obj);
    }

1.1 ==

class Person {
    public String name;
    public String gender;
    public int age;

    Person(String name,String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public String toString() {
        return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }
}


public class Test {
    public static void main(String[] args) {
        //1,==比较基本数据类型
        int a = 10;
        int b = 10;
        System.out.println(a == b);

        //2. ==比较引用数据类型
        Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("泡泡","女",19),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };
        System.out.println(person[0] == person[1]);
        System.out.println(person[0].equals(person[1]));
    }

}

打印结果为:
在这里插入图片描述\

1.2 equals方法

有些情况下,需要比较的是对象中的内容,这时需要重写equals方法,比如上述例子,我们可以看到person[0]与person[1]这两个对象的内容都是一样的,所以我们希望equals方法比较的时候返回的是true

class Person {
    public String name;
    public String gender;
    public int age;

    Person(String name,String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public String toString() {
        return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }

    @Override
    public boolean equals(Object o) {
        //自己和自己比较
        if(this == o) {
            return true;
        }
        //o是null对象或者o不是Person类
        if(o == null || !(o instanceof Person)) {
            return false;
        }

        Person p = (Person)o;
        //基本数据类型如age为int类型可以直接用==比较
        //引用类型最好还是用equals比较
        return name.equals(p.name) && gender.equals(p.gender) && age == p.age;
    }
}


public class Test {
    public static void main(String[] args) {
        //比较引用数据类型
        Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("泡泡","女",19),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };
        System.out.println(person[0] == person[1]);
        System.out.println(person[0].equals(person[1]));
    }

}

打印结果如下:
在这里插入图片描述
因为==实际上还是调用的默认equals方法,对象的地址进行比较,所以打印false,而重写了equals后,再进行比较,我们看到person[0]与person[1]的内容完全一致,所以返回true

equals方法覆写的通用步骤:

  1. 如果指向同一个对象,返回 true
  2. 如果传入的为 null或者传入的对象类型不是该类的,返回false
  3. 按照自己的规则,完成类的实现目标比较
  4. 注意在重写的时候用其他引用类型的比较也需要 equals,例如这里的name,gender的比较

缺点】equals方法只能比较是否相等,不能按照大于、小于的方式进行比较

1.3 ==和equals方法的区别

==
对于基本数据类型,比较的是值
对于引用数据类型,比较的是对象的内存地址

因为Java只有值传递,所以,==不管是比较基本数据类型还是引用数据类型变量, 其本质比较的都是值,只是引用类型变量存的值是对象的地址

equals方法
equals方法比较的也是对象的内存地址,但是可以重写equals,按照自己的比较规则来比较内容是否相等

2. 大于/小于关系

下面我们来看看这个例子,给一个对象数组排序,能否直接用已经有的sort方法呢~

class Person {
    public String name;
    public String gender;
    public int age;

    Person(String name,String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public String toString() {
    return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }

}
public class Test1 {
    public static void main(String[] args) {
        Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("西西","男",33),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };

        Arrays.sort(person);
        System.out.println(Arrays.toString(person));

    }
}

运行结果:运行出错,抛出异常
在这里插入图片描述
答案是显然不行的,因为整数之间是可以直接比较,大小关系明确。但是两个学生对象的大小关系无法确定,需要我们自己额外指定,下面介绍两种方法:

2.1 实现Comparable接口

即Person类实现Comparable接口,并重写该接口的compareTo方法
Comparble是JDK提供的泛型的比较接口类,T代表泛型,实现过程具体如下:

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

在这里插入图片描述
(一) 以下为使用Comparable接口,按上述例子,年龄进行从大到小排序的代码:

class Person implements Comparable{
    public String name;
    public String gender;
    public int age;

    Person(String name,String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public String toString() {
    return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }

    public int compareTo(Object o) {
        Person p = (Person)o;
        if(this.age > p.age) {
            return -1;
        }else if(this.age < p.age) {
            return 1;
        }else {
            return 0;
        }
        //上述判断可以直接写成
        //return p.age - this.age; 
        //该两个对象比较打印结果为年龄差值
    }

}
public class Test1 {
    public static void main(String[] args) {
        Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("西西","男",33),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };
        //两个对象的比较
        System.out.println(person[0].compareTo(person[1]));
        //对象数组排序
        Arrays.sort(person);
        System.out.println(Arrays.toString(person));

    }
}

运行结果如下:
在这里插入图片描述
解释说明
(1) 表达当前对象大于参数对象
在这里插入图片描述
(2) 在sort方法中会自动调用compareTo方法,compareTo的参数是Object,其实传入的是Person类型的对象,比较当前对象与参数对象的大小关系,可以自己定义比较哪个参数(比如这里按年龄来算的)

1> 如果当前对象应排在参数对象前,返回小于0的数字
2> 如果当前对象应排在参数对象后,返回大于0的数字
3> 如果当前对象与参数对象不分先后,返回0

(3) 如果想让年龄从小到大排序呢~即把大于号改成小于号,小于号改成大于号,记住想让当前对象排在参数对象前,返回值需要小于0

 public int compareTo(Object o) {
        Person p = (Person)o;
        if(this.age < p.age) {
            return -1;
        }else if(this.age > p.age) {
            return 1;
        }else {
            return 0;
        }
    }
 public int compareTo(Object o) {
        Person p = (Person)o;
      	return this.age - p.age;
    }

(二) 以下为使用Comparable接口带泛型的代码:

class Person implements Comparable<Person>{
    public String name;
    public String gender;
    public int age;

    Person(String name,String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public String toString() {
    return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }

    public int compareTo(Person o) {
        return this.age - o.age;
    }

}
public class Test1 {
    public static void main(String[] args) {
        Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("西西","男",33),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };
        System.out.println(person[0].compareTo(person[1]));
        Arrays.sort(person);
        System.out.println(Arrays.toString(person));

    }
}

打印结果如下:年龄按从小到大排序
在这里插入图片描述
缺点】容易写死,写死就固定下来了~
总结即可以在一个类中实现Comparable接口,并实现该接口的方法comparaTo方法,可按照自己指定规则,进行比较排序

2.2 Comparator比较器

按照比较器比较的方式具体步骤如下:
(1) 用户自定义比较器类,实现Comparator接口

 public interface Comparator<T> {
        // 返回值:
        // < 0: 表示o1指向的对象小于o2指向的对象
        // == 0: 表示o1指向的对象等于o2指向的对象
        // > 0: 表示o1指向的对象大于o2指向的对象
        int compare(T o1,T o2);
    }

在这里插入图片描述
(2) 重写Comparator中的compare方法,上述例子代码如下:

import java.util.Comparator;

class Person implements Comparable<Person>{
    public String name;
    public String gender;
    public int age;

    Person(String name,String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public String toString() {
        return "[" + this.name + ":" + this.gender + " "+ this.age + "]";
    }


    @Override
    public int compareTo(Person o) {
        return this.age-o.age;
    }
}

class PersonAgeComparator implements Comparator<Person> {

    @Override
    public int compare(Person o1, Person o2) {
        return o2.compareTo(o1);
    }
}

public class Test2 {

    public static void main(String[] args) {
            Person[] person = new Person[] {
                new Person("泡泡","女",19),
                new Person("西西","男",33),
                new Person("柚柚","女",25),
                new Person("球球","男",25)
        };

        //定义比较器对象
        PersonAgeComparator tor = new PersonAgeComparator();
        //使用比较器对象进行比较
        System.out.println(tor.compare(person[0],person[1]));
    }
}

运行结果:
在这里插入图片描述注意
(1) Comparator是java.util 包中的泛型接口类,使用时必须导入对应的包,即import java.util.Comparator;
(2) 这里不能直接使用Arrays.sort来排序对象数组,因为没有重写compareTo方法,sort方法中会自动调用compareTo方法

2.3 三种重写方法的比较

在这里插入图片描述💛💛💛本期内容回顾💛💛💛
在这里插入图片描述✨✨✨本期内容到此结束啦~下期再见!


网站公告

今日签到

点亮在社区的每一天
去签到