最近项目中有许多地方用到了集合排序,不是自然排序,必须的自己实现排序逻辑了。
java提供实现排序接口有两个Comparable与Comparator。
我简单理解:
1.Comparable接口是实现在需要排序的单个对象上的,例如:Student学生类,根据学号或其他属性排序,Student类就要implements实现Comparable接口,并重写int compareTo(T o) 方法。你排序所依赖的所有元素都需要包含在Student类里,换言之就是依赖在Student类里能获取到的资源。然后直接调用Collections.sort(List<T> list) 方法就行了,比较方便。
但是,有一点需要注意,Comparable接口比较局限,就是继承Comparable接口类只能实现Student的一种排序,换一种排序,你就需要重新编写Student基础类了。
2.Comparator接口是可以单独拿来实现的,每个实现Comparator接口都可以有一种排序的逻辑。继承Comparator接口需要实现 int compare(String o1, String o2)方法。然后直接调用Collections.sort(List<T> list, Comparator<? super T> c)方法。
Comparator接口就比较自由了,每个实现Comparator接口都可以有自己实现逻辑,无需修改需要排序的对象,比较灵活。并且所依赖的元素不局限于需要排序对象本身的属性,可以把需要的资源任意添加实现Comparator接口的类中。
例如:
class SchoolRoomComparator implements Comparator<String>{ Map<String,SchoolRoom> schoolRoomMap; public SchoolRoomComparator(){ this.schoolRoomMap = schoolRoomMap; } @Override public int compare(String o1, String o2) { return schoolRoomMap.get(o1).getXuhao() - schoolRoomMap.get(o2).getXuhao(); } }
用到了出了需要排序的String对象外,还依赖schoolRoomMap属性。
下面我说说我程序报的异常吧。
异常:Comparison method violates its general contract!
我这里就简单阐述一下,我用的是Comparator接口实现的排序。由于业务需要,在比较Double对象大小时,我用了Math.ceil(double a)
方法,错误的把需要比较的Double对象转化成了整数,忽略了小数部分。违反了Comparator 要满足自反性,传递性,对称性。
参考博客:https://blog.csdn.net/wangxueming/article/details/80967341