Comparable 与 Comparator 的区别
1、Comparable
Comparable 可以认为是一个内比较器,实现了Comparable 接口的类有一个特点,就是这些类可以和自己比较,至于具体和另外一个实现了Comparable 接口的类如何比较,则需要依赖compareTo方法的实现,compareTo方法也被称为自然比较方法,如果开发者add进入一个Collection的对象想要用Colllections.sort()方法,进行排序的话,那么这个对象必须实现Comparable 接口。
package action;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Student implements Comparable<Student>{
private int age;
private String name;
public Student(int age) {
super();
this.age = age;
}
public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int compareTo(Student o) {
if(this.age - o.getAge() > 0){
return 1;
}else if (this.age - o.getAge() < 0) {
return -1;
}else {
return 0;
}
}
@Override
public String toString() {
return "Student [age=" + age + "]";
}
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student(8));
list.add(new Student(9));
list.add(new Student(11));
list.add(new Student(10));
System.out.println(list);
Collections.sort(list);
Student s1 = new Student(5);
Student s2 = new Student(9);
System.out.println(s1.compareTo(s2));
System.out.println(list);
}
}
最终是使用二分查找的对数组[]进行排序,
注意一下,前面说实现Comparable接口的类是可以支持和自己比较的,但是其实代码里面Comparable<T>泛型未必一定是实现此接口的类(如:Student),也可以是String或者其他类型都可以,只要开发者指定可具体的比较算法就可以。
2、Comparator
Comparator 可以认为是一个外比较器,个人认为有两种情况可以使用Comparator接口;
- 一个对象不支持自己可自己比较(没有实现Comparable接口),但是又想对两个对象进行比较;
- 一个对象实现了Comparable接口,但是开发着认为compareTo方法中的比较方式并不是自己想要的那种表达方式;
Comparator 接口里面有一个compare方法,方法中有两个参数T o1 和 T o2,是泛型的表示方式,分别表示待比较的两个对象,方法返回值和 Comparable接口一样是 int 。
package actionPerform;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Student {
private int age;
private String name;
public Student(int age) {
super();
this.age = age;
}
public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + "]";
}
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student(8));
list.add(new Student(9));
list.add(new Student(11));
list.add(new Student(10));
System.out.println(list);
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
if (o1.getAge() - o2.getAge() > 0) {
return 1;
} else if (o1.getAge() - o2.getAge() < 0) {
return -1;
} else {
return 0;
}
}
});
System.out.println(list);
}
}
当然因为泛型指定死了,所以实现Comparator 接口的实现类只能是两个相同的对象;
3、总结
两种比较器 Comparator 和 Comparable ,相比有点如下:
- 如果实现类没有实现 Comparable 接口,又想对两个类进行比较(或者实现类实现Comparable 接口,但是对compareTo方法内的比较算法不满意),那么可以实现Comparator 接口,自定义一个比较器,写比较算法;
- 实现 Comparable 接口的方式比实现 Comparator 接口的耦合性要强一些,如果要修改比较算法,要修改Comparable的实现类,而实现 Comparator 的类是在外部进行比较的,不需要对实现类进行修改。从这个角度上说,尤其是我们将实现类的 .class 文件打成一个 .jar 文件提供给开发者使用时。实际上实现Comparator 接口的方式,就是一种典型的策略模式。