背景
在使用Collections#sort方法对集合进行排序的时候可能并不是很清楚到底是默认的排序规则、自定义排序规则、自定义排序器等等,那么Comparable与Comparator接口到底是有什么区别?该如何使用?
Comparable接口(内部比较器)
1、comparable接口位于java.lang包下,并且很多基本类型的包装类实现了该接口,比如:String,Integer,Double等,当我们使用集合排序的时候,如果集合内元素对象已经实现了Comparable接口,那么集合内部会根据该对象的compareTo方法进行排序处理,默认很多基本类型的包装类元素已经实现了该接口,所以也不需要我们手动实现该接口,但当我们自定义了一个对象的时候,如也需要一定的规则排序,那么就需要实现该接口从而重写compareTo排序方法,如:
public class Employee implements Comparable<Employee>{
private String name;
private Integer age;
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Employee o) {
int i = this.name.compareTo(o.getName());
if(i == 0){
return this.age.compareTo(o.getAge());
}
return i;
}
}
集合排序写法如下:
Employee employee = new Employee();
employee.setAge(23);
employee.setName("B");
Employee employee1 = new Employee();
employee1.setAge(23);
employee1.setName("A");
Employee employee2 = new Employee();
employee2.setAge(23);
employee2.setName("C");
List<Employee> employees = Arrays.asList(employee, employee1,employee2);
System.out.println("没排序之前:"+ employees);
Collections.sort(employees);
System.out.println("对象使用排序接口:"+employees);
2、运行结果
没排序之前:[Employee{name=‘B’, age=23}, Employee{name=‘A’, age=23}, Employee{name=‘C’, age=23}]
对象使用排序接口:[Employee{name=‘A’, age=23}, Employee{name=‘B’, age=23}, Employee{name=‘C’, age=23}]
Comparator接口(外部比较器)
1、Comparator接口位于java.util包下,当集合中元素不能满足自比较的情况下,可以在进行集合元素排序的代码里嵌入自定义外部排序器,同时也可以做到定义些复杂的排序规则。
public class EmployeeComparator implements Comparator<Employee> {
@Override
public int compare(Employee o1, Employee o2) {
int i = o1.getAge().compareTo(o2.getAge());
if(i == 0){
return o1.getName().compareTo(o2.getName());
}
return i;
}
}
Collections.sort(employees, new EmployeeComparator());
System.out.println("使用排序器:"+employees);
2、运行结果
使用排序器:[Employee{name=‘A’, age=23}, Employee{name=‘B’, age=23}, Employee{name=‘C’, age=23}]
总结
1、Comparable接口的方式更加高内聚,后续如果规则修改,只需要修改实现该接口的对象源代码即可。
2、Comparator接口的方式更加容易维护,职责分明,低耦合,规则修改后只需要修改对应的排序器代码即可,同时还可以实现更加复杂的排序规则。