🥰🥰🥰来都来了,不妨点个关注叭!
👉博客主页:欢迎各位大佬!👈
本期内容满满干货,将会深入介绍对象与对象之间是如何进行比较的,我们知道基本数据类型是可以直接比较大小的,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 + "]";}@Overridepublic 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 + "]";}@Overridepublic int compareTo(Person o) {return this.age-o.age;}
}class PersonAgeComparator implements Comparator<Person> {@Overridepublic 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 三种重写方法的比较
💛💛💛本期内容回顾💛💛💛
✨✨✨本期内容到此结束啦~下期再见!