一般来说,Comparable 是为了对某个类的集合进行排序,所以此时一般都是这个需要排序的类本身去实现 Comparable 接口。换句话说,如果某个类实现了 Comparable 接口,那么这个类的数组或者说 List 就可以进行排序了。很多时候我们无法对类进行修改,或者说此类修改的成本太高,但是又希望对其进行排序。那怎么办?这个时候 Comparator 接口就排上了用场。
例如:
1 | public final class Employee { |
Employee 类没有实现 Comparable 接口,并且加上了 final 关键字,但是还是需要对其排序,怎么办?
如果在 JDK8 之前,使用匿名内部类的方式:
1 | public static void test() { |
在 JDK8 之后,可以使用 lambda 表达式:
1 | public static void test() { |
如果将此方法 run 起来,输出如下:
1 | [name is: ccc, salary is: 80, name is: aaa, salary is: 100, name is: bbb, salary is: 150] |
Comparable 接口中只有一个 compareTo 方法要实现,而 Comparator 有两个方法,但是我们只实现了一个方法,那么另外一个方法呢?
其实很简单,因为另外一个方法是 equals 方法。所有的类都继承了 Object 类,而 Object 类中实现了 equals 方法,所以我们这里不实现 equals 方法也无所谓。
Comparator 中的各种实现方式比较
1. 传统的匿名内部类
1 | Collections.sort(list, new Comparator<Employee>() { |
2. lambda 表达式
1 | list.sort((Employee e1, Employee e2) -> e1.getSalary() - e2.getSalary()); |
2.1 精简版的 lambda 表达式:
1 | list.sort((e1, e2) -> e1.getSalary() - e2.getSalary()); |
2.2 使用 Comparator.comparing 的方式:
我们使用上述 lambda 表达式的时候,IDE 会提示我们:can be replaced with comparator.comparing Int
。
1 | list.sort(Comparator.comparing(employee -> employee.getSalary())); |
2.3 使用静态方法的引用
::
是 JDK8 里引入 lambda 后的一种用法,表示方法引用,比如静态方法的引用 String::valueOf
,比如构造器的引用 ArrayList::new
。
1 | list.sort(Comparator.comparing(Employee::getSalary)); |
2.4 排序反转(逆序)
1 | list.sort(Comparator.comparing(Employee::getSalary).reversed()); |
多条件组合排序
1. 传统的匿名内部类
1 | list.sort((e1, e2) -> { |
2. lambda 表达式
从 JDK8 开始,我们现在可以把多个 Comparator 链在一起(chain together)去建造更复杂的比较逻辑。
1 | list.sort(Comparator.comparing(Employee::getSalary).thenComparing(Employee::getName)); |
如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理