Comparable
Comparable接口,进行元素的排序,通常是自己和自己比较,相当于内比较器,就是将比较器写在类里面,比较方法是compareTo()。比如Integer或者String对象可以进行排序,实际上就是实现了Comparable的compareTo()方法,实现了自然排序。
当需要对自定义对象进行排序,需要按照自定义的方式进行排序,我们就可以在自定义的类实现Comparable接口,然后重写compareTo方法。比如:
public class Student implements Comparable<Student>{
int age;
int height;
String name;
int id;
public Student(String name, int age, int height){
this.age = age;
this.height = height;
this.name = name;
}
@Override
public int compareTo(Student std){
//先比较年龄
if(this.age!=std.age){
return this.age>std.age?1:-1;
}
//年龄相等就比较身高
if(this.height!=std.height){
return this.height>std.height?1:-1;
}
return 0;
}
public void setId(int id){
this.id = id;
}
}
可以发现,这时候排序是先根据学生的年龄升序排,年龄相同时,按照身高升序排。但是如果这时候,学生都安排一个学号,又需要加入学号排序的条件。如果学生类是别人提供的,已经封装好了,就不可能再去类内部重写compareTo()方法了,这时候Comparable比较器的局限性出现了,所以我们尝试使用Comparator比较器去实现。
Comparator
Comparator是一个外部定义比较器,可以根据需求修改排序规则。当一个对象的类中没有实现Comparable接口(即不能自己和自己比较)或者重写的compareTo()方法不能满足当前业务需求,此时就需要实现Comparator接口,重写compare()比较方法来定义排序规则。
public class studentComparator implements Comparator<Student>{
@Override
public int compare(Student s1, Student s2){
//先根据学号id比较
if(s1.id!=s2.id){
return s1.id>s2.id?1:-1;
}
//再根据学生年龄比较排序
if(s1.age!=s2.age){
return s1.age>s2.age?1:-1;
}
//再根据学生升高比较排序
if(s1.height!=s2.height){
return s1.height>s2.height?1:-1;
}
return 0;
}
}
像这样直接定义一个外部类比较器实现Comparator接口,就可以完成自定义规则排序。不管是Comparable还是Comparator,它们的返回值均为1,0,-1。如果返回的是1那就是从小到大排,如果返回的是-1那就是从大到小。
最常见的Arrays.sort()的排序方法就是将Comparator作为比较器参数进行排序的。
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}