西红柿小生|从排序角度浅析Comparable和Comparator

Comparable是java.lang包下的接口 , Comparator是java.util包下的接口 , 从字面上看两者都用来做比较 , 定义一个接口不就OK了吗 , 为啥多此一举定义两个?
ComparableComparable是排序接口 , 让实现该接口的类具备排序的能力 。 实现了Comparable接口的类的对象的列表或数组可以通过Collections.sort或Arrays.sort进行自动排序 。 jdk中的String,Integer,Double等类型都已默认实现了Comparable接口 , 我们可以直接使用 。 该接口有且只有一个方法 , 定义如下:
compareTo方法接受任意类型的对象 , 返回值是int类型;会抛出以下两种异常:
NullPointerException:如果对象o为null , 抛出空指针异常ClassCastException:如果需要类型转换之后进行比较 , 可能会抛出类型转换异常对于o1.compareTo(o2) , 结果有三种情况:
负整数 , 意味着比较者o1比被比较者o1小;返回零 , 意味着o1等于o2;返回正整数 , 意味着o1大于o2 。 【西红柿小生|从排序角度浅析Comparable和Comparator】定义一个Student类 , 实现Comparable接口并重写了compareTo方法 , 使得该类的对象支持按age由小到大排序 , 代码如下图所示:
定义一个测试类ComparableTest , main方法定义并初始化一个students数组 , 通过Arrays工具类的sort方法进行排序 , 最后输出排序结果 , 如下图所示:
其结果如下图所示:
ComparatorComparator是比较接口 , 作用和Comparable类似 , 也使用Collections.sort和Arrays.sort来进行排序 , TreeMap和TreeSet等数据结构底层也是使用Comparator实现 。 jdk1.8之后多了不少方法 , 但这里主要介绍compare方法 , 其作用和Comparable的compareTo类似 , 用于比较两个对象大小 , 使用中也会抛NullPointerException和ClassCastException两类异常 , 其定义如下图所示:
Comparator适用排序场景有:
类本身不支持排序 , 即没有实现Comparable接口;类实现了Comparable接口 , 但需要使用不同于compareTo方法的比较方式进行比较 , 如:维度和顺序等定义一个比较器StudentComparator , 比较器按rank维度从小到大排序 , 代码如下图所示:
定义一个测试类ComparatorTest , main方法定义并初始化一个students数组 , 通过Arrays工具类的sort方法进行排序 , 最后输出排序结果 , 如下图所示:
其结果如下图所示:
由上图可以看出 , 虽然Student类已经实现了Comparable接口 , 本身支持按age排序 , 但通过Comparator比较器 , 我们还可以使Student类按rank排序 。
Comparable和Comparator区别通过前面对Comparable和Comparator的分析可知 , 两者之间的主要区别有:
Comparable在java.lang基本包中 , Comparator在java.util工具包中;Comparable有且只有compareTo一个方法 , Comparator除了compare还有多个其他方法;Comparable是内部排序 , 需要修改源代码 , 耦合度高 , Comparator是外部排序 , 不需要修改源代码 , 耦合度低;Comparable让类按照某一单一的固定逻辑进行排序 , Comparator可以让类有选择的灵活排序;使用中对于Comparable , 只需要传入一组实现该接口的对象即可 , 而对于Comparator , 还需额外指定实现了Comparator接口的比较器对象 。 一道面试题如何让HashMap按value从小到大顺序输出键值对?
思路:HashMap本身是无序不支持排序的 , 故考虑通过Comparator比较器实现排序;另外HashMap不属于List子类 , 不能使用Collections.sort进行排序 , 故需要先将HashMap中的元素取出放入ArrayList中 。
java修身之路 , 专注java学习和分享 , 不止java 。