🥰🥰🥰来都来了,不妨点个关注叭!
👉博客主页:欢迎各位大佬!👈
本期内容满满干货,将会深入介绍对象与对象之间是如何进行比较的,我们知道基本数据类型是可以直接比较大小的,Java中引用类型的变量不能直接按照大于或者小于的方式进行比较,那为什么==可以比较呢?我们一起带着这些问题来了解本期内容
文章目录
- 1. 等于关系
- 1.1 ==
- 1.2 equals方法
- 1.3 ==和equals方法的区别
- 2. 大于/小于关系
- 2.1 实现Comparable接口
- 2.2 Comparator比较器
- 2.3 三种重写方法的比较
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方法覆写的通用步骤:
- 如果指向同一个对象,返回 true
- 如果传入的为 null或者传入的对象类型不是该类的,返回false
- 按照自己的规则,完成类的实现目标比较
- 注意在重写的时候用其他引用类型的比较也需要 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 三种重写方法的比较
💛💛💛本期内容回顾💛💛💛
✨✨✨本期内容到此结束啦~下期再见!