当前位置 > 主页 > 万和大讲堂 >


南京Java培训解惑:Comparable 和 Comparator 的区别

2016-12-15 11:43

  Java 中为我们提供了两种比较机制:Comparable 和 Comparator,他们之间有什么区别呢?今天南京万和Java培训带大家来了解一下。


  Comparable 自然排序


  Comparable 在 java.lang 包下,是一个接口,内部只有一个方法 compareTo():



  Comparable 可以让实现它的类的对象进行比较,具体的比较规则是按照 compareTo 方法中的规则进行。这种顺序称为 自然顺序。


  compareTo 方法的返回值有三种情况:


  e1.compareTo(e2) > 0 即 e1 > e2


  e1.compareTo(e2) = 0 即 e1 = e2


  e1.compareTo(e2) < 0 即 e1 < e2


  注意:


  1.由于 null 不是一个类,也不是一个对象,因此在重写 compareTo 方法时应该注意 e.compareTo(null) 的情况,即使 e.equals(null) 返回 false,compareTo 方法也应该主动抛出一个空指针异常 NullPointerException。


  2.Comparable 实现类重写 compareTo 方法时一般要求 e1.compareTo(e2) == 0 的结果要和 e1.equals(e2) 一致。这样将来使用 SortedSet 等根据类的自然排序进行排序的集合容器时可以保证保存的数据的顺序和想象中一致。


  有人可能好奇上面的第二点如果违反了会怎样呢?


  举个例子,如果你往一个 SortedSet 中先后添加两个对象 a 和 b,a b 满足 (!a.equals(b) && a.compareTo(b) == 0),同时也没有另外指定个 Comparator,那当你添加完 a 再添加 b 时会添加失败返回 false, SortedSet 的 size 也不会增加,因为在 SortedSet 看来它们是相同的,而 SortedSet 中是不允许重复的。


  实际上所有实现了 Comparable 接口的 Java 核心类的结果都和 equlas 方法保持一致。


  实现了 Comparable 接口的 List 或则数组可以使用 Collections.sort() 或者 Arrays.sort() 方法进行排序。


  实现了 Comparable 接口的对象才能够直接被用作 SortedMap (SortedSet) 的 key,要不然得在外边指定 Comparator 排序规则。


  因此自己定义的类如果想要使用有序的集合类,需要实现 Comparable 接口,比如:


  上述代码还重写了 equlas(), hashCode() 方法,自定义的类将来可能会进行比较时,南京万和Java培训建议重写这些方法。


  这里南京万和Java培训想表达的是在有些场景下 equals 和 compareTo 结果要保持一致,这时候不重写 equals,使用 Object.equals 方法得到的结果会有问题,比如说 HashMap.put() 方法,会先调用 key 的 equals 方法进行比较,然后才调用 compareTo。


  后面重写 compareTo 时,要判断某个相同时对比下一个属性,把所有属性都比较一次。


  Comparable 接口属于 Java 集合框架的一部分。


  Comparator 定制排序


  Comparator 在 java.util 包下,也是一个接口,JDK 1.8 以前只有两个方法:



  JDK 1.8 以后又新增了很多方法:



  基本上都是跟 Function 相关的,这里暂不介绍 1.8 新增的。


  从上面内容可知使用自然排序需要类实现 Comparable,并且在内部重写 comparaTo 方法。


  而 Comparator 则是在外部制定排序规则,然后作为排序策略参数传递给某些类,比如 Collections.sort(), Arrays.sort(), 或者一些内部有序的集合(比如 SortedSet,SortedMap 等)。


  使用方式主要分三步:


  创建一个 Comparator 接口的实现类,并赋值给一个对象


  在 compare 方法中针对自定义类写排序规则


  将 Comparator 对象作为参数传递给 排序类的某个方法


  向排序类中添加 compare 方法中使用的自定义类


  南京万和Java培训举个例子:



  其实可以看到,Comparator 的使用是一种策略模式。


  排序类中持有一个 Comparator 接口的引用:



  而我们可以传入各种自定义排序规则的 Comparator 实现类,对同样的类制定不同的排序策略。


  总结


  Java 中的两种排序方式:


  Comparable 自然排序。(实体类实现)


  Comparator 是定制排序。(无法修改实体类时,直接在调用方创建)


  同时存在时采用 Comparator(定制排序)的规则进行比较。


  对于一些普通的数据类型(比如 String, Integer, Double…),它们默认实现了Comparable 接口,实现了 compareTo 方法,我们可以直接使用。


  而对于一些自定义类,它们可能在不同情况下需要实现不同的比较策略,我们可以新创建 Comparator 接口,然后使用特定的 Comparator 实现进行比较。


  以上这就是南京万和Java培训总结的 Comparable 和 Comparator 的区别,你们都get了吗?


最近开班 more>
  • 全栈开发
  • 前端基础班
  • 软件测试
  • Java大数据开发工程师
  • 云原生精英班
  • 开发课程基础班第四期
  • 开发课程基础班第三期
  • 开发课程基础班第二期
  • 开发课程基础班第一期
  • Java Web UI Python
  • CISP
  • HCIE-Datacom(HCIA,HCIP基础)
  • HCIP-Datacom(HCIA基础)
  • HCIA-Datacom(0基础)
  • HCIE-Datacom(HCIA,HCIP基础)
  • HCIP-Datacom(HCIA基础)
  • HCIA-Datacom(0基础)
  • OCM 12C
  • OCP 19C
  • RHCE 9.0
  • 脱产班
  • 脱产班
  • 脱产班
  • 脱产班
  • 脱产班
  • 脱产班
  • 脱产班
  • 脱产班
  • 脱产班
  • vip班
  • 考试计划
  • 脱产班
  • 脱产班
  • 脱产班
  • 双休班
  • 双休班
  • 双休班
  • 双休班
  • 业余班
  • 业余班
  • 10月16日
  • 9月23日
  • 9月2日
  • 9月30日
  • 8月26日
  • 10月8日
  • 9月23日
  • 9月16日
  • 9月9日
  • 随时开课
  • 9月21日
  • 10月17日
  • 9月18日
  • 9月2日
  • 11月2日
  • 10月26日
  • 9月7日
  • ——
  • 随时开课
  • 9月26日
    • 姓 名 :
    • 电 话 :
    • 课 程 :

技术交流群

  • Java大数据交流群560819979加入
  • Python技术交流群595083299加入
  • Oracle技术交流群595119011加入
  • Web前端技术交流群604697610加入
  • Huawei技术交流群482919361加入
  • Redhat技术交流群587875348加入
  • UI设计技术交流群511649801加入
  • Cisco技术交流群596886705加入
  • IT运维技术交流群605888381加入