前言
Hello大家好呀,在java中我们常常涉及到对象的比较,不同于基本数据类型,对于我们的自定义对象,需要我们自己去建立比较标准,例如我们自定义一个People类,这个类有name和age两个属性,那么问题来了,你如何比较两个人呢?很明显这个时候我们只有建立一个比较标准,只根据名字或者年龄比较,这个时候就需要Comparable和Comparator接口了,下面我将带领大家学习这两个接口
一,二者区别
首先呢,我想先为大家区别一下二者:Comparable与Comparator在逻辑上相似,都是根据比较对象的大小不同返回一个整型。但是类重写Comparable的compareTo方法只有一个,通常定义在要比较的类内部,由类的对象调用传入另一个该类的对象来比较,这当然有它的局限性,因为一个类中只能有一个compareTo方法,因此,只能指定一种比较标准,就像在刚才举例的Person类中重写comparable方法的话,只能指定按照名字或者年龄直接一种来排,但是在某些即需要我们根据名字排序,也需要我们根据年龄来排序的情境中就头疼了,因为compareTo方法没有重载,这个时候就需要Comparator接口,我们可以定义不同的按照不同标准比较两个对象的类来运用compare方法比较,现在听不懂也没关系,下面会为大家说明代码细节。
二,Comparable接口
以前面的Person类为例让类继承Comparable接口,同时按住Alt+Enter按键一直按到底,编译器会自动生成一段代码
这段代码没什么稀奇的,我们肯定是要重写它,但是我们需要注意它是传了一个Object的参数,(当然我们也可以自己修改成Person)这个参数需要我们强转成我们需要比较的对象才能够使用,那么我们先根据较简单的年龄比较,因为他是一个整形数据,如果调用该方法的对象年龄大于传入对象是返回一个大于0的数,他们年龄相等时返回0,否则返回一个小于0的数,于是我们得到了这样一段代码
当然,这段代码可不可以优化呢?显然,因为是整型数据的比较,可以写成下面的形式
ok那么我们就实现了用年龄比较两个Person对象的方法,后面内容我们会用这个方法实现一个排序算法这里先不测试这个方法继续往下讲,那么显然,对于String类型的name,不支持我们减号来比较两个对象的属性该怎么办呢?答案是,再调用一次ConpareTo方法
当然,这个时候调用的就是String内部的compareTo方法,我们不必关心代码实现细节,这也再次体现了封装的好处,我们不妨看看String是怎么实现这个方法的,按住ctrl鼠标点击这个方法便可以查看源码
当然我们这个时候,只要会用这个方法就行,代码放在下面,大家也能看出它的局限性,就是说下面我写根据姓名比较Person对象时必须把写过的根据年龄比较的代码注调
public class Test {
public static void main(String[] args) {
}
}
class Person implements Comparable {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// @Override
// public int compareTo(Object o) {
// Person tmp=(Person) o;//使用之前需强转
// return this.age-tmp.age;
// }
@Override
public int compareTo(Object o) {
Person tmp=(Person) o;//使用之前需强转
return this.name.compareTo(tmp.name);
}
}
三,Comparator接口
实现Comparator的compare方法与compareTo方法初始情况知识compare方法多了一个参数
我们已经说过最好新建一个比较类根据不同标准比较,与compareTo方法的区别是这里不能由对象调用,也就是不能存在this,然后代码实现细节和compareTo差别不大,大家可以看看下面这段代码思考一下Comparator接口怎么实现根据不同标准比较的
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
class AgeCompare implements Comparator<Person>{
//这里<Person>是声明这个接口用于比较Person类,这部分知识后面还会讲
@Override
public int compare(Person person, Person t1) {
return person.age-t1.age;
}
}
class NameCompare implements Comparator<Person>{
@Override
public int compare(Person person, Person t1) {
return person.name.compareTo(t1.name);
}
}
我们再比较时只需实例化一个比较类在调用方法传入两给person对象就好啦
四,冒泡排序实现排序person对象
代码实现细节都放在注释里啦,先上代码
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
Person person1=new Person("a",15);
Person person2=new Person("b",12);
Person person3=new Person("c",17);
Person person4=new Person("d",13);
Person person5=new Person("e",19);//实例化五个对象
Person[] people={person1,person5,person3,person2,person4};//乱序
Sort.sort(people);//这个时候就排好了
System.out.println(people[0]);
System.out.println(people[1]);
System.out.println(people[2]);
System.out.println(people[3]);
System.out.println(people[4]);
}
}
class Person implements Comparable{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Object o) {
return this.age-((Person)o).age;
}
}
class Sort {
public static void sort(Comparable[] comparable) {
//注意这里用接口数组表示实现了这个接口也就是这个数组一定是可比较的
for (int i = 0; i < comparable.length - 1; i++) {
for (int j = 0; j < comparable.length - 1; j++) {
//标准冒泡排序
if (comparable[j].compareTo(comparable[j + 1]) > 0) {
//因为比较的是任意类型数据,这里一定是调用我们重写的compareTo方法
Comparable tmp=comparable[j];
comparable[j]=comparable[j+1];
comparable[j+1]=tmp;
}
}
}
}
}
注意我们如果要修改排序顺序选择修改compareTo方法,修改一行代码即可
改为
同样,要根据名字排序也只需动compareTo方法
这样我们的排序就完成啦
本期博客就到这里,感谢大家阅读,我们下期见