比较器Comparable和Comparator的使用和区别
Comparable
api中的描述:
public interface Comparable该接口对实现它的每个类的对象强加一个整体排序。 这个排序被称为类的自然排序 ,类的compareTo方法被称为其自然比较方法 。
- Comparable为实体类添加了一个默认的排序方式称为自然排序
- Comparable是实体类实现的接口,并且重写compareTo
public int compareTo(T o)
- this 与传入的对象o进行比较
- 根据返回值判断this与o的大小,负数为小(this<o),等于为相同,正数为大于
// 先比名字,名字相比年龄,年龄相同比成绩。
@Override
public int compareTo(Student o) {
int res = this.name.compareTo(o.getName());
if (res == 0) {
res = this.age - o.getAge();
if (res == 0){
res = Double.compare(this.score, o.getScore());
}
}
return res;
}
- 如上图,this在前为正序(从小到大),this在后为逆序(从大到小)
- double 类型精度不准,所以使用double的包装类Double的compare方法
- 传入的类型有问题会报ClassCastException
- 使用Arrays.sort()或Collections.sort()方法会自动调用compareTo方法,
Arrays.sort(students);
这样就引出一个问题,如何不修改以前的代码,改变排序方式?于是就引出了Comparator
Comparator
public interface Comparator比较功能,对一些对象的集合施加了一个整体排序 。 可以将比较器传递给排序方法(如Collections.sort或Arrays.sort ),以便对排序顺序进行精确控制。
- 对一些对象的集合施加了一个整体排序
- 在实体类外创建一个类实现Comparator接口,使用的时候直接在Collections.sort或Arrays.sort 传入改类对象即可
- 需要实现compare方法
int compare(T o1,T o2)
- 使用方式与Comparable接口的compareTo方法类似
- o1在前为正序,o1在后为逆序
// 按照年龄排序
public class CompareByAge implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
}
使用:Arrays.sort(students,compareByAge);
,数组使用Arrays.sort,集合使用Collections.sort
Comparator中还有一些方法
// 返回一个比较器,强制该比较器的相反顺序。
default Comparator<T> reversed()
// 用另一个比较器返回一个字典顺序比较器。
default Comparator<T> thenComparing(Comparator<? super T> other)
- thenComparing 可以传入另一个比较器对象,实现多排序,例如先按年龄排序,年龄相同使用分数排序
Arrays.sort(students,compareByAge.thenComparing(compareByScore));
- 以上两个方法可以使用链式编程调用
注意:Comparable给实体类添加了一个自然排序方式,Comparator是对集合添加的排序。如果一个类实现了Comparable接口,当调用Comparator实现类对象时并没有覆盖实体类的Comparable自然排序,只是暂时改变了排序方式