对象间的比较和排序——Comparable和Comparator的使用
前言
在开发过程中,我们可能需要根据某种规则来对集合对象或者对象和对象之间进行排序,JDK提供了Comparable和Comparator两种实现方式让我们去实现对象间的比较和排序。本篇文章将对两种实现方式进行简单的讲解。
在java中,对于基本数据的数值,我们可以直接通过>
、<
、=
来直接进行比较。也可以用Arrays.sort
来对数值或者字符类型的数组进行排序。但是对象间的比较,和排序我们就无法简单通过上述方法去解决了,因为对象比较的前提,是存在比较和排序的规则,而不同的对象可能各有各的使用场景和比较规则,所以需要我们自己使用JDK提供的API进行定义。
方法一:实现Comparable接口
Comparable接口是JDK1.2的时候推出的,若一个类实现了Comparable接口,那么这个类就可以支持使用Arrays.sort
以及Collections.sort
来进行排序。排序规则的核心在于对接口中的compareTo
方法进行定义。
package java.lang;
public interface Comparable<T> {
/**
* 返回0,表示相等
* 返回正数,表示当前对象this大于被比较对象
* 返回负数,表示当前对象this小于被比较对象
*/
int compareTo(T var1);
}
使用小案例
public class Student implements Comparable<Student> {
private String name;
private int age;
@Override
public int compareTo(Student otherStu) {
if(this.age > otherStu.age){
return 1;
}else if(this.age < otherStu.age){
return -1;
}else{
return 0;
}
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
在测试类测试
@Test
public void comparableTest(){
Student s1 = new Student("小明",10);
Student s4 = new Student("大明",18);
Student s2 = new Student("小红",4);
Student s3 = new Student("大红",20);
List<Student> list = new ArrayList<>(Arrays.asList(s1,s2,s3,s4));
Collections.sort(list);
System.out.println(list);
// [Student{name='小红', age=4}, Student{name='小明', age=10}, Student{name='大明', age=18}, Student{name='大红', age=20}]
}
通过输出结果我们可以看到,list
中的各个元素已经按照我们定义好的规则进行了排序
方法二:通过Comparator接口自定义比较器
自定义Student类比较器
public class Student {
private String name;
private int age;
... 省略get、set和toString和构造方法
}
public class StudentComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
if(s1.getAge() > s2.getAge()){
return 1;
}else if(s1.getAge() < s2.getAge()){
return -1;
}
return 0;
}
}
比较器的定义和实现Comparable
接口比较相似,定义两个对象的比较规则,大于为正数、小于为负数。接下来我们在测试类中进行测试:
@Test
public void comparableTest(){
Student s1 = new Student("小明",10);
Student s4 = new Student("大明",18);
Student s2 = new Student("小红",4);
Student s3 = new Student("大红",20);
List<Student> list = new ArrayList<>(Arrays.asList(s1,s2,s3,s4));
Collections.sort(list,new StudentComparator());
System.out.println(list);
// [Student{name='小红', age=4}, Student{name='小明', age=10}, Student{name='大明', age=18}, Student{name='大红', age=20}]
}
我们在使用sort
方法进行排序的时候,将自定义比较器作为参数传入即可。
小总结
上面我们一共讲了两种方法来实现对象间的比较,那么这两种方法有什么不同呢?
- Comparable需要类在内部实现该接口,比较的时候直接使用
Collections.sort
方法即可 - Comparator接口是非入侵式的,也就是说当我们需要对类进行扩展的时候,不用变动到原有类的结构变化,而是新建一个满足业务需要的比较器,并且在Comparator里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。