相关文章
在 Java 中,我们可以使用 Comparable 或者 Comparator 来实现两个元素之间比较与排序,现在让我们一起来看看它们之间有什么区别
一、Comparable
-
Comparable 是一个内部比较器,表示有能力比较的,其核心方法是
compareTo(T o)
-
当一个类实现了 Comparable 接口时,除了要实现
compareTo(T o)
方法外,我们还要覆盖equals(Object obj)
和hashCode()
方法,这是遵守了 Object.hashCode 的通用约定-
equals() 相等的两个对象,它们的 hashCode() 也一定相等
-
hashCode() 相等的两个对象,它们的 equals() 不一定相等
-
-
当我们使用
Collections.sort()
方法来对集合进行排序时,如果集合中存储的是自定义对象,则需要实现 Comparable 接口 -
举例说明
-
Student.java
public class Student implements Comparable<Student> { private String name; private Integer age; public Student(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public int compareTo(@NonNull Student student) { // 先按照name排序 if (this.name.compareTo(student.name) > 0) { return 1; } if (this.name.compareTo(student.name) < 0) { return -1; } // 再按照age排序 if (this.age.compareTo(student.age) > 0) { return 1; } if (this.age.compareTo(student.age) < 0) { return -1; } return 0; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Student student = (Student) o; if (!name.equals(student.name)) { return false; } return age.equals(student.age); } @Override public int hashCode() { int result = name.hashCode(); result = 31 * result + age.hashCode(); return result; } }
-
ComparableTest.java
public class ComparableTest { public static void main(String[] args) { TreeSet<Student> treeSet = new TreeSet<>(); treeSet.add(new Student("Tom", 22)); treeSet.add(new Student("Tom", 18)); treeSet.add(new Student("Amy", 20)); treeSet.forEach(System.out::println); } } // Student(name=Amy, age=20) // Student(name=Tom, age=18) // Student(name=Tom, age=22)
-
如上所示,Student 类实现了 Comparable 接口,并实现了 compareTo() 方法中的业务逻辑,先按照学生姓名从小到大排序,再按照学生年龄从小到大排序,如果两个都相等,则视为相同对象
-
在 main() 方法中,我们往 TreeSet 中添加了三个学生对象,排序结果如注释所示,符合预期结果
-
二、Comparator
-
Comparator 是一个外部比较器,表示用于比较的工具,适用于那些没有实现 Comparable 接口或者已经实现但对已有排序规则不满意的类,使用起来更加灵活,其核心方法是
compare(T o1, T o2)
接口 -
举例说明
-
StudentComparator.java
public class StudentComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } }
-
ComparableTest.java
public class ComparableTest { public static void main(String[] args) { TreeSet<Student> treeSet = new TreeSet<>(new StudentComparator()); treeSet.add(new Student("Tom", 22)); treeSet.add(new Student("Tom", 18)); treeSet.add(new Student("Amy", 20)); treeSet.forEach(System.out::println); } } // Student(name=Tom, age=18) // Student(name=Amy, age=20) // Student(name=Tom, age=22)
-
如上所示,StudentComparator 实现了 Comparator 接口,并实现了 compare() 方法中的业务逻辑,只比较学生年龄,从小到大排序
-
在 main() 方法中,我们往 TreeSet 的构造方法中添加了 StudentComparator,并往 TreeSet 中添加了三个学生对象,排序结果如注释所示,符合预期结果
-
这里值得注意的,此时 Student 类本身实现了 Comparable 接口,同时比较器中实现了 Comparator 接口,当两者并存时,Comparator 的优先级要大于 Comparable
-
三、归纳总结
-
Comparable
- 内部比较器,表示有能力比较的
-
Comparator
- 外部比较器,表示用于比较的工具