jdk1.8.0_144

一知半解写代码, 集合排序用个啥。 抄起键盘胡乱打, 似懂非懂最可怕。

  Comparable与Comparator都是用于集合的排序,对于大多数人来说Comparator可能略微比Comparable要熟悉一点,类似下面这几句代码的使用频率应该是最高的。

Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});

  这是一段对集合排序的代码。

  对于集合排序时比较器的使用往往止步于此,以至于更为深层次的使用似懂非懂,更为复杂的排序不知所措。

  Comparable用于集合内部定义的方法实现的排序,Comparator用于集合外部实现的排序。

  我们从Collections.sort的两个重载方法开始

public static <T extends Comparable<? super T>> void sort(List<T> list)

public static <T> void sort(List<T> list, Comparator<? super T> c)

  这两个方法都是泛型方法,第一个方法只传递一个List参数进行排序,第二个方法传递一个List参数加上一个Comparator比较器。

public static <T extends Comparable<? super T>> void sort(List<T> list)

  Collections.sort方法用于对List集合进行排序,思考一个问题,这个只有一个参数的List如何进行排序呢?它是按照怎样的规则进行排序呢?答案就在这个泛型方法的泛型类型之中“<T extends Comparable<? super T>>”,List集合中的元素需要实现Comparable接口,Comparable接口也是一个泛型,并要求它的泛型类型需要是集合中的元素的超类(或自身)。重点在于——集合中的元素需要是实现Comparable接口。也就是说在使用Collections.sort(List)这个方法对集合中的元素进行排序时,需要集合中的元素实现了Comparable接口,这才能进行排序。

 

public static <T> void sort(List<T> list, Comparator<? super T> c)

  这个方法同样是一个泛型方法,与上面的方法不同的是对集合中的元素类型并没有做限制,要对这个集合进行排序需要指定一个Comparator比较器,这个比较器的泛型类型需要是集合元素的超类(或自身)。

  通过上面这两个方法比较容易的能得出一个浅显的结论,Comparable和Comparator都是用于比较、排序,如果元素自身已经实现了Comparable接口,则可以利用它自身进行比较排序,如果元素自身没有实现Comparable接口,则可以利用外部实现Comparator比较器对元素进行比较排序。这也就是前面提到的Comparable用于集合内部定义的方法实现的排序,Comparator用于集合外部实现的排序。 接着来看Comparable接口和Comparator接口。

  接着来看Comparable接口和Comparator接口。

Comparable

public int compareTo(T o)

  这个接口只定义了一个compareTo方法,在很多“值类型”的数据类型,例如String、Integer、Long等已经实现了这个接口。

  对于这个方法和equals方法有类似的地方,equals强调的更多是相等于否,而compareTo强调更多的比较,如果x < y,则返回-1;x = y,则返回0;x > y,则返回1。实现这个方法时同样需要遵循几个规则:

  1. 自反性,如果x <y ,那么x.compareTo(y)返回-1,同理y.compareTo则返回1;
  2. 传递性,如果x.compareTo(y)返回-1,y.compareTo(z)返回-1,则x.compareTo(z)也应该返回-1;
  3. 同一性,如果x.compareTo(y)返回0(x = y),那么若x.compareTo(z)返回-1时,y.compareTo(z)也应该返回-1。

  有兴趣的可以查看String类中对于compareTo方法的实现,它的排序规则是将字符串转换为字符数组逐个按照字典序排序。

Comparator

int compare(T o1, T o2)

boolean equals(Object obj)

  这个接口在JDK8中对它进行了较大的改进,在JDK8之前只包含上面两个方法,而JDK8则达到了18个方法,其中都是接口的default方法,和static静态方法,所以并不需要在实现时额外实现。

  在JDK8中该类添加了@FunctionalInterface函数式接口的注解,函数式接口表明在接口中只含有一个方法作为Lambda表达式的数据类型,在《JDK8的新特性——Lambda表达式》中有提到,Java中定义如果覆盖了Object中的方法则不算,所以在Comparator接口中只有一个compare方法。对于@FunctionalInteface注解可加不可加,加上只是为了让编译器做更好的检查,要求只能定义一个方法,不加编译器便不对此进行检查。

  compare方法和compareTo方法类似,它同样需要满足上面提到的:自反性、传递性、同一性。并且它强调,不必严格满足“(compare(x, y)==0) == (x.equals(y))”,当然最好说明白。

  对于这个类,更多的是需要理解学习它所运用的设计模式——策略模式。策略模式,不改变对象自身,而是用另一个对象来改变它的行为。例如,超市减价操作,有10件商品需要统一降价1半进行处理,我们可以在这10件商品的价格上全部做修改减少至它的一半,10件好处理,如果N件呢,甚至我们还需要对其进行降价呢?此时我们则可以使用一种“策略”——商品全部打5折。这就是利用另外一个对象来改变一个对象的行为,而不是简单粗暴地修改原有对象。说回此处,如果List中的元素本身没有实现Comparable接口,但我们需要对它进行排序,我们可以对原有对象进行修改让它实现Comparable接口,但凡涉及修改代码都不优美,此时我们则可以利用策略模式,也就是实现一个Comparator接口对集合中的元素进行排序。

这是一个能给程序员加buff的公众号 

似懂非懂的Comparable与Comparator的更多相关文章

  1. Java中Comparable与Comparator的区别

    相同 Comparable和Comparator都是用来实现对象的比较.排序 要想对象比较.排序,都需要实现Comparable或Comparator接口 Comparable和Comparator都 ...

  2. 对象比较器:Comparable和Comparator

    在进行对象数组排序的过程中需要使用到比较器,比较器有两个:Comparable和Comparator ①.java.lang.Comparable:是在类定义是时候默认实现好的接口,里面提供有一个co ...

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

    Java中Comparable和Comparator接口区别分析 来源:码农网 | 时间:2015-03-16 10:25:20 | 阅读数:8902 [导读] 本文要来详细分析一下Java中Comp ...

  4. Comparable和Comparator的区别

    Comparable Comparable可以认为是一个内比较器,实现了Comparable接口的类有一个特点,就是这些类是可以和自己比较的,至于具体和另一个实现了Comparable接口的类如何比较 ...

  5. Java中Comparable和Comparator区别小结

    一.Comparable简介 Comparable是排序接口.若一个类实现了Comparable接口,就意味着该类支持排序.实现了Comparable接口的类的对象的列表或数组可以通过Collecti ...

  6. Java 中 Comparable 和 Comparator 比较

    Java 中 Comparable 和 Comparator 比较 目录: Comparable Comparator Comparable 和 Comparator比较 第二个例子 之 Compar ...

  7. Comparable与Comparator

    转载 Comparable与Comparator的区别 (转载) Comparable & Comparator 都是用来实现集合中元素的比较.排序的,只是 Comparable 是在集合内部 ...

  8. Java中的TreeMap、Comparable、Comparator

    我们知道HashMap的存储位置是按照key这个对象的hashCode来存放的,而TreeMap则是不是按照hashCode来存放,他是按照实现的Comparable接口的compareTo这个方法来 ...

  9. 比较器comparable与comparator的使用

    在Java学习和使用里,工具类与算法类(collections和Arrays)也是我们使用比较多的,在它们里面就包含了comparable与comparator这两种比较器. 一.比较器的分类与概念 ...

随机推荐

  1. LockSupport理解

    一.背景 在看并发包源码的时候看见过LockSupport,今天恰巧看到LockSupport字眼,于是看下jdk1.7中的源码结构.想着它应该是运用多线程的锁工具的,到底似乎怎么实现的呢? 二.使用 ...

  2. 记录idea maven项目打包部署web项目mapper扫描失败

    最开始以为这里出了问题,后来加上以后还是不能把mapper.xml打包进去 这是报的异常信息 Mybatis启动老是报绑定错误(找不到Mapper对应的 SQL配置),经过一番Google未能解决问题 ...

  3. memcached集群和一致性哈希算法

    场景 由于memcached集群各节点之间都是独立的,互不通信,集群的负载均衡是基于客户端来实现的,因此需要客户端用户设计实现负载均衡算法. 取模算法 N个节点,从0->N-1编号,key对N ...

  4. qq客服代码实现过程

    引入css,jsimages,将index.html中的qq聊天代码部分和返回顶部-部分放在head.html文件中, 将文中圈中部分删除,否则影响整个页面的样式:

  5. PHP move_uploaded_file() 函数

    PHP Filesystem 函数 定义和用法 move_uploaded_file() 函数将上传的文件移动到新位置. 若成功,则返回 true,否则返回 false. 语法 move_upload ...

  6. sublime text如何保存为uft-8无bom编码格式文件

    https://jingyan.baidu.com/article/9158e000388092a2541228b6.html 今天发现自己的文件突然多了很多特殊符号,真是奇了怪,查找html里面也并 ...

  7. git分支小问题

    参考网址:http://hbiao68.iteye.com/blog/2055493 1.查看分支 git branch 或者 git branch -v 2.创建一个新的分支 git branch ...

  8. flannel 网络问题排查

    1. 如果你发现 k8s容器无法访问外网? 重启docker 原因是,docker重启后会重新生成网桥.网络不通的原因是flannel启动后生成的网络覆盖了docker的网络,当你重启docker后, ...

  9. JS-输入金额校验

    function clearNoNum(obj){    obj.value = obj.value.replace(/[^\d.]/g,"");  //清除"数字&qu ...

  10. webpack的四大核心概念

    webpack中文文档:https://doc.webpack-china.org/concepts/ 一.Entry(入口) 1.单个入口(简写)语法 // 语法 entry: string|Arr ...