点击关注公众号,实用技术文章及时了解

来源:blog.csdn.net/u010859650/article/details/85009595

Comparable 简介

Comparable 是排序接口。

若一个类实现了Comparable接口,就意味着“该类支持排序”。此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器。接口中通过x.compareTo(y)来比较x和y的大小。若返回负数,意味着x比y小;返回零,意味着x等于y;返回正数,意味着x大于y。

Comparator 简介

Comparator 是比较器接口。我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现Comparator接口即可。也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。

int compare(T o1, T o2)和上面的x.compareTo(y)类似,定义排序规则后返回正数,零和负数分别代表大于,等于和小于。

两者的联系

Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。

另外,附送学习资源:Java进阶视频资源

代码实现

package com.github.compare;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;/*** @                           _ooOoo_*                            o8888888o*                            88" . "88*                            (| -_- |)*                            O\  =  /O*                         ____/`---'\____*                       .'  \\|     |//  `.*                      /  \\|||  :  |||//  \*                     /  _||||| -:- |||||-  \*                     |   | \\\  -  /// |   |*                     | \_|  ''\---/''  |   |*                     \  .-\__  `-`  ___/-. /*                   ___`. .'  /--.--\  `. . __*                ."" '<  `.___\_<|>_/___.'  >'"".*               | | :  `- \`.;`\ _ /`;.`/ - ` : | |*               \  \ `-.   \_ __\ /__ _/   .-` /  /*          ======`-.____`-.___\_____/___.-`____.-'======*                             `=---='*          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*                     佛祖保佑        永无BUG*@DESCRIPTION Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。*             Comparable相当于“内部比较器”*@AUTHOR SongHongWei*@PACKAGE_NAME com.github.compare**/
public class ComparableAndCompartor
{public static void main(String[] args){List<House> houses = new ArrayList();House h1 = new House(95.0, 12000);House h2 = new House(110.0, 12160);House h3 = new House(80.0, 16300);House h4 = new House(150.3, 10690);houses.add(h1);houses.add(h2);houses.add(h3);houses.add(h4);comparable(houses);comparator(houses);}/***@DESCRIPTION House类实现类Comparable接口, 并重写了compareTo方法, 所以执行Collections.sort方法时会去调用我们重写的compareTo方法*@AUTHOR SongHongWei*@TIME 2018/12/14-16:46*@CLASS_NAME ComparableAndCompartor**/private static void comparable(List houses){System.out.printf("未排序前的顺序,%s\n", houses);Collections.sort(houses);System.out.printf("按面积大小排序后的顺序,%s\n", houses);}private static void comparator(List houses){System.out.printf("未排序前的顺序,%s\n", houses);Collections.sort(houses, new ComparatorDetail());System.out.printf("按单价大小排序后的顺序,%s\n", houses);}/***@DESCRIPTION 实现Compatator接口, 并重写compare方法, 根据单价倒序排序*@AUTHOR SongHongWei*@TIME 2018/12/14-16:49*@CLASS_NAME ComparableAndCompartor**/static class ComparatorDetail implements Comparator<House>{@Overridepublic int compare(House o1, House o2){if (o1.price < o2.price)return 1;else if (o1.price > o2.price)return -1;return 0;}}
}
package com.github.compare;/*** @                           _ooOoo_*                            o8888888o*                            88" . "88*                            (| -_- |)*                            O\  =  /O*                         ____/`---'\____*                       .'  \\|     |//  `.*                      /  \\|||  :  |||//  \*                     /  _||||| -:- |||||-  \*                     |   | \\\  -  /// |   |*                     | \_|  ''\---/''  |   |*                     \  .-\__  `-`  ___/-. /*                   ___`. .'  /--.--\  `. . __*                ."" '<  `.___\_<|>_/___.'  >'"".*               | | :  `- \`.;`\ _ /`;.`/ - ` : | |*               \  \ `-.   \_ __\ /__ _/   .-` /  /*          ======`-.____`-.___\_____/___.-`____.-'======*                             `=---='*          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*                     佛祖保佑        永无BUG*@DESCRIPTION 一个房子对象, 有面积和单价两个属性*@AUTHOR SongHongWei*@PACKAGE_NAME com.github.compare**/
public class House implements Comparable<House>
{/*房子的面积*/protected double proportion;/*房子每平米的售价*/protected double price;public House(double proportion, double price){this.proportion = proportion;this.price = price;}/***@DESCRIPTION 重写compareTo方法, 利用房子的面积来进行大小比较*@AUTHOR SongHongWei*@TIME 2018/12/14-16:18*@CLASS_NAME House**/@Overridepublic int compareTo(House o){/*当前对象的面积大,返回正数*/if (this.proportion > o.proportion)return 1;/*当前面积小,返回负数*/else if (this.proportion < o.proportion)return -1;/*相等返回0*/return 0;}@Overridepublic String toString(){return "面积为" + proportion + "\t价格为" + price;}
}

附注

Collection与Collections的区别

Collection是集合类的上级接口,继承与他有关的接口主要有List和Set

Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全等操作

public static void main(String args[]) {   //注意List是实现Collection接口的   List list = new ArrayList();   double array[] = { 112, 111, 23, 456, 231 };   for (int i = 0; i < array.length; i++) {   list.add(new Double(array[i]));   }   Collections.sort(list);   //把list按从小到大排序for (int i = 0; i < array.length; i++) {   System.out.println(list.get(i));   }   // 结果:23.0 111.0 112.0 231.0 456.0   }

Collections如何调用重写的compareTo方法的

集合框架中,Collections工具类支持两种排序方法:

Collections.sort(List<T> list);
Collections.sort(List<T> list, Comparator<? super T> c)

如果待排序的列表中是数字或者字符,可以直接使用Collections.sort(list);当需要排序的集合或数组不是单纯的数字型时,需要自己定义排序规则,实现一个Comparator比较器。

Collections调用Collections.sort(list)方法,方法传递一个List集合,这里要求,List泛型里面装的元素必须实现Compareable接口此外,列表中的所有元素都必须是可相互比较的(也就是说,对于列表中的任何 e1 和 e2 元素,e1.compareTo(e2) 不得抛出 ClassCastException)。

Java源码里是这样写的

All elements in the list must implement the {@link Comparable}interface.Furthermore, all elements in the list must be <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)} must not throw a {@code ClassCastException} for any elements

Collections.sort源码

public static <T extends Comparable<? super T>> void sort(List<T> list) {Object[] a = list.toArray();Arrays.sort(a);ListIterator<T> i = list.listIterator();for (int j=0; j<a.length; j++) {i.next();i.set((T)a[j]);}}

由源码可以看出来,sort内部调用了Arrays.sort的方法,继续向下看

Arrays.sort源码

public static void sort(Object[] a) {if (LegacyMergeSort.userRequested)legacyMergeSort(a);elseComparableTimSort.sort(a);}

源码里首先判断是否采用传统的排序方法,LegacyMergeSort.userRequested属性默认为false,也就是说默认选中 ComparableTimSort.sort(a)方法(传统归并排序在1.5及之前是默认排序方法,1.5之后默认执行ComparableTimSort.sort()方法。除非程序中强制要求使用传统归并排序,语句如下:System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"))

继续看 ComparableTimSort.sort(a)源码

ComparableTimSort.sort(a)源码

static void sort(Object[] a) {sort(a, 0, a.length);}static void sort(Object[] a, int lo, int hi) {rangeCheck(a.length, lo, hi);int nRemaining  = hi - lo;if (nRemaining < 2)return;  // Arrays of size 0 and 1 are always sorted// If array is small, do a "mini-TimSort" with no mergesif (nRemaining < MIN_MERGE) {int initRunLen = countRunAndMakeAscending(a, lo, hi);binarySort(a, lo, hi, lo + initRunLen);return;}/*** March over the array once, left to right, finding natural runs,* extending short natural runs to minRun elements, and merging runs* to maintain stack invariant.*/ComparableTimSort ts = new ComparableTimSort(a);int minRun = minRunLength(nRemaining);do {// Identify next runint runLen = countRunAndMakeAscending(a, lo, hi);// If run is short, extend to min(minRun, nRemaining)if (runLen < minRun) {int force = nRemaining <= minRun ? nRemaining : minRun;binarySort(a, lo, lo + force, lo + runLen);runLen = force;}// Push run onto pending-run stack, and maybe mergets.pushRun(lo, runLen);ts.mergeCollapse();// Advance to find next runlo += runLen;nRemaining -= runLen;} while (nRemaining != 0);// Merge all remaining runs to complete sortassert lo == hi;ts.mergeForceCollapse();assert ts.stackSize == 1;}

nRemaining表示没有排序的对象个数,方法执行前,如果这个数小于2,就不需要排序了。

如果2<= nRemaining <=32,即MIN_MERGE的初始值,表示需要排序的数组是小数组,可以使用mini-TimSort方法进行排序,否则需要使用归并排序。

mini-TimSort排序方法:先找出数组中从下标为0开始的第一个升序序列,或者找出降序序列后转换为升序重新放入数组,将这段升序数组作为初始数组,将之后的每一个元素通过二分法排序插入到初始数组中。注意,这里就调用到了我们重写的compareTo()方法了。

private static int countRunAndMakeAscending(Object[] a, int lo, int hi) {assert lo < hi;int runHi = lo + 1;if (runHi == hi)return 1;// Find end of run, and reverse range if descendingif (((Comparable) a[runHi++]).compareTo(a[lo]) < 0) { // Descendingwhile (runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) < 0)runHi++;reverseRange(a, lo, runHi);} else {                              // Ascendingwhile (runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) >= 0)runHi++;}return runHi - lo;}

推荐:

主流Java进阶技术(学习资料分享)

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!

Java中Comparable和Comparator接口的区别相关推荐

  1. java comparator相等_详解Java中Comparable和Comparator接口的区别

    详解Java中Comparable和Comparator接口的区别 发布于 2020-7-20| 复制链接 摘记: 详解Java中Comparable和Comparator接口的区别本文要来详细分析一 ...

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

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

  3. JAVA语言-比较器Comparator(java中Comparable和Comparator的区别)

    文章目录 一.什么是Comparator 二.Java compare方法和compareTo方法 三.java中Comparable和Comparator的区别 Comparator的例子 三.de ...

  4. 简单介绍Java中Comparable和Comparator

    转载自 简单介绍Java中Comparable和Comparator Comparable 和 Comparator是Java核心API提供的两个接口,从它们的名字中,我们大致可以猜到它们用来做对象之 ...

  5. Java中Comparable和Comparator实现对象比较

    Java中Comparable和Comparator实现对象比较 目录 一. Comparator 二. Comparable 三.比较 当需要排序的集合或数组不是单纯的数字型时,通常可以使用Comp ...

  6. Java中Comparable和Comparator的区别

    前言 最近复习遇到了这个问题,在此进行一个详细的记录,分享给大家. 两个接口的区别 包区别 Comparable接口是在java.lang下. Comparator接口是在java.util下. 使用 ...

  7. Java中Comparable和Comparator区别小结

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

  8. Java中Comparable与Comparator的区别

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

  9. JAVA中Comparable和 Comparator的区别

    Comparable 和 Comparator比较 简介 Comparable 1.1说明 1.2举例 Comparator 1.1说明 1.2举例 相同点: 不同点: 简介 Comparable 和 ...

最新文章

  1. Mysql错误:服务名无效。 请键入 NET HELPMSG 2185 以获得更多的帮助。
  2. 搭建Docker环境---私有仓库registry搭建
  3. python强类型_python动态性强类型用法实例
  4. sockaddr_in中sin_zero的意义,以及sockaddr_in sockaddr in_addr区别联系
  5. 超燃| 2019 中国.NET 开发者峰会视频发布
  6. gwt格式_GWT的渐进式Web应用程序配方
  7. android 修改系统参数设置,2021-05-15 [RK3399][Android7.1] 调试笔记 ---显示参数动态设置接口...
  8. Derby与mysql的关系_Derby数据库简单介绍和使用方法 | 学步园
  9. JavaScript事件与处理程序绑定(1)
  10. superoneclick 2.2_总投资2.2亿!又一年产10万吨水性乳液项目开工
  11. Atitit 衡量项目的规模
  12. 活动目录管理中常用的脚本(二)
  13. 【长期更新】关于各网盘、下载客户端、BT技术
  14. 【Linux】C语言——贪吃蛇
  15. 图像渲染测试软件,3D渲染参数(测试图及光子图)
  16. 计算机无法识别机械硬盘,机械硬盘无法识别【面对办法】
  17. golang反射的类型Type与种类Kind使用
  18. react+mobx+jquery构建大型工具项目经验总结
  19. 自动驾驶的分级和无人驾驶系统简介
  20. 12、Kanzi插件——创建Kanzi Engine插件的方法

热门文章

  1. 汽车行业持续亏损?奥迪:不存在的
  2. 2019胡润女企业家榜公布:碧桂园杨惠妍继续领跑
  3. 太晚了!iPhone屏下指纹或要等到2021年才安排
  4. 5G牌照提前发放 将对整个产业界带来哪些影响?
  5. 2999元!联想Z6 Pro开启预售:搭载骁龙855+后置高清四摄
  6. 拳王虚拟项目公社:如何如何打造虚拟自动盈利系统,用虚拟资源实现被动收入?
  7. c++中使用libxml2读取xml文件【转】
  8. Linux的shell编程(四)
  9. Java并发编程之调度线程池
  10. Android 动画 Animator 家族