项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
欢迎大家star,留言,一起学习进步

1.两个接口的原型

Java中,Comparable与Comparator接口都是用来做比较的。那么这两个接口在实际使用中到底有什么不同呢?下面我们来结合实例分析一下。

先看看两个接口在JDK中的原型。

package java.lang;
import java.util.*;public interface Comparable<T> {public int compareTo(T o);
}
package java.util;import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
import java.util.Comparators;@FunctionalInterface
public interface Comparator<T> {int compare(T o1, T o2);boolean equals(Object obj);
}

2.Comparable的用法

一般来说,Comparable是为了对某个类的集合进行排序,所以此时一般都是这个需要排序的类本身去实现Comparable接口。换句话说,如果某个类实现了Comparable接口,那么这个类的数组或者说List就可以进行排序了。

举个简单的例子:

public class Employee implements Comparable<Employee> {private String name;private int salary;public Employee(String name, int salary) {this.name = name;this.salary = salary;}@Overridepublic int compareTo(Employee other) {return this.salary - other.salary;}@Overridepublic String toString() {return "name is: " + name + ", salary is: " + salary;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getSalary() {return salary;}public void setSalary(int salary) {this.salary = salary;}
}

在客户端中实现Employee集合排序:

public class CompareTest {public static List<Employee> genList() {Employee e1 = new Employee("aaa",100);Employee e2 = new Employee("bbb",150);Employee e3 = new Employee("ccc", 80);List<Employee> list = new ArrayList();list.add(e1);list.add(e2);list.add(e3);return list;}public static void t1() {List<Employee> list = genList();//Collections.sort(list); 两种方式都可以,此种方式源码中就是调用的list.sort(null)list.sort(null);System.out.println(list);}public static void main(String[] args) {t1();}}

将客户端的代码run起来,最后输出的结果为:

[name is: ccc, salary is: 80, name is: aaa, salary is: 100, name is: bbb, salary is: 150]

因为Employee实现了Comparable接口,所以能直接对Employee数组进行排序。

3.Comparator接口用法

很多时候我们无法对类进行修改,或者说此类修改的成本太高,但是又希望对其进行排序。那怎么办?这个时候Comparator接口就排上了用场。
比如我们将前面的Employee类稍作修改,不实现Comparable接口,加上final关键字:

public final class Employee  {private String name;private int salary;public Employee(String name, int salary) {this.name = name;this.salary = salary;}@Overridepublic String toString() {return "name is: " + name + ", salary is: " + salary;}...此处省略get/set
}

这个时候我们显然无法修改Employee类了。但是还是需要对其排序,怎么办?

如果在jdk8之前,使用匿名内部类的方式:

    public static void test() {List<Employee> list = genList();Collections.sort(list, new Comparator<Employee>() {@Overridepublic int compare(Employee o1, Employee o2) {return o1.getSalary() - o2.getSalary();}});System.out.println(list);}

在jdk8之后,可以使用lambda表达式:

    public static void test() {List<Employee> list = genList();Comparator<Employee> comparator = (Employee e1, Employee e2) -> e1.getSalary() - e2.getSalary();list.sort(comparator);System.out.println(list);}

如果将此方法run起来,输出如下:

[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方法也无所谓!

4.Comparator中的各种实现方式比较

Comparator中的compare方法实现方式还是比较多的。下面我们来一一说明。

4.1 传统的匿名内部类

JDK8之前,一般是采用匿名内部类的方式实现:

        Collections.sort(list, new Comparator<Employee>() {@Overridepublic int compare(Employee o1, Employee o2) {return o1.getSalary() - o2.getSalary();}});

4.2 lambda表达式

JDK8之后,可以使用lambda表达式:

list.sort((Employee e1, Employee e2) -> e1.getSalary() - e2.getSalary());

4.3 精简版的lambda表达式

我们通过不指定类型定义来进一步简化表达式,因为编译器自己可以进行类型判断

list.sort((e1, e2) -> e1.getSalary() - e2.getSalary());

4.4 使用Comparator.comparing的方式

我们使用上述lambda表达式的时候,IDE会提示我们:can be replaced with comparator.comparing Int

list.sort(Comparator.comparing(employee -> employee.getSalary()));

4.5 使用静态方法的引用

java中的双冒号就是方法引用。::是JDK8里引入lambda后的一种用法,表示引用,比如静态方法的引用String::valueOf,比如构造器的引用,ArrayList::new。

list.sort(Comparator.comparing(Employee::getSalary));

4.6 排序反转

很多时候,想对排序进行反转,或者说逆序:

list.sort(Comparator.comparing(Employee::getSalary).reversed());

4.7 许多条件组合排序

        list.sort((e1, e2) -> {if(e1.getSalary() != e2.getSalary()) {return e1.getSalary() - e2.getSalary();} else {return e1.getName().compareTo(e2.getName());}});

4.8 从JDK 8开始,我们现在可以把多个Comparator链在一起(chain together)去建造更复杂的比较逻辑

list.sort(Comparator.comparing(Employee::getSalary).thenComparing(Employee::getName));

Comparable 与 Comparator 比较相关推荐

  1. Java 中 Comparable 和 Comparator 比较

    为什么80%的码农都做不了架构师?>>>    本文,先介绍Comparable 和Comparator两个接口,以及它们的差异:接着,通过示例,对它们的使用方法进行说明. Comp ...

  2. Java 解惑:Comparable 和 Comparator 的区别

    读完本文你将了解到: Comparable 自然排序 Comparator 定制排序 总结 Java 中为我们提供了两种比较机制:Comparable 和 Comparator,他们之间有什么区别呢? ...

  3. 对象比较:Comparable 和 Comparator

    java中我们如何给对象排序?这就必须借助Comparator 或 Comparable.有了他们就意味着你可用实现对象之间的比较.也就可用做到排序了. Comparable Comparable 也 ...

  4. Java核心API -- 7(Iterator迭代器、Comparable、Comparator比较器)

    1. Iterator迭代器 所有Collection的实现类都实现了iterator方法,该方法返回一个Iterator接口类型的对象,用于实现对集合元素迭代的便利.在java.util包下. 1) ...

  5. java compareto方法怎么排序的_深入理解Java中Comparable和Comparator排序

    本文有牛旦教育原创,头条首发,转载注明来源. 如何为需要的排序算法选择正确的接口?通过本文的分析讲解,我们会找到答案参考答案. 程序员经常需要将数据库中的元素排序为集合.数组或映射.在Java中,我们 ...

  6. Java中Comparable和Comparator区别小结

    阅读目录 一.Comparable简介 二.Comparator简介 三.Comparable和Comparator区别比较 回到顶部 一.Comparable简介 Comparable是排序接口.若 ...

  7. comparable和comparator比较

      今天在翻阅TreeMap的源码,发现其键必须是实现Comparable或者Comparator的接口时产生了一些兴趣,比如在TreeMap中的put方法分别对Comparable和Comparat ...

  8. Java中Comparable与Comparator的区别

    一.概述 Comparable和Comparator都是用来实现集合中元素的比较.排序的. Comparable是在集合内部定义的方法实现的排序,位于java.util下. Comparator是在集 ...

  9. Comparable与Comparator浅析

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  10. Java中Comparable和Comparator接口区别分析

    本文要来详细分析一下Java中Comparable和Comparator接口的区别,两者都有比较的功能,那么究竟有什么区别呢,感兴趣的Java开发者继续看下去吧. Comparable 简介 Comp ...

最新文章

  1. java·环境变量、基本数据类型
  2. cad2016中选择全图字体怎么操作_LOL无限火力凯隐全图W技能BUG怎么卡 无限火力凯隐全图W技能BUG卡法介绍...
  3. 【收藏】如何查看linux服务器内存使用情况
  4. MySQL kill操作
  5. Composite(组合)--对象结构型模式
  6. 【Ubuntu】ubuntu系统下python3和python2环境自由切换
  7. 在spring boot中三分钟上手apache顶级分布式链路追踪系统skywalking
  8. 解决SQL查询总是 超时已过期
  9. 自适应谱线增强matlab,自适应谱线增强器.doc
  10. vivado 使用DDS IP方法
  11. c++ stl string char* 向 string 转换的问题
  12. XmlDataProvider的简单应用
  13. Wireshark入门:第一次亲密接触
  14. 傲腾内存不支持linux吗,内存英特尔® 傲腾™常见问题
  15. Mellanox网卡不能分配VF解决方法
  16. iAd框架详细解析 —— ASM
  17. ubuntu使用bitbucket
  18. Debian修改DNS
  19. VLAN规划原则与建议
  20. C# 简单判断枚举值是否被定义

热门文章

  1. laravel Ajax请求 X-CSRF验证问题
  2. 李瑾博士:信誉的建立是否“不计成本”?
  3. PostgreSQL导出导入schema相关
  4. css3ps—ps直接生成css3 使用方法
  5. Windows 無法查詢{7B849a69-220F-......} 的 DllName 登錄項目
  6. 考前必练15道题_《系统集成项目管理工程师备考宝典》
  7. 加速nginx: 开启gzip
  8. 20180529 Linux配置ip 排查问题
  9. MySQL存储引擎--MYSIAM和INNODB引擎区别
  10. 大数据技术将是传统企业创新的原点