这是我参与8月更文挑战的第27天,活动详情查看:8月更文挑战
前言
compareTo方法没有定义在Object类中,而是Comparable接口中唯一的方法,不但允许进行简单的等同性比较,而且允许执行顺序比较。一旦实现了Comparable接口,就说明它是自然有序的。就可以跟许多泛型方法以及依赖于该接口的集合实现类进行协作。
实例
public class User implements Comparable<User>{
...
@Override
public int compareTo(User o) {
return 0;
}
}
返回的是int,负数代表小于,0代表等于,正数代表大于
实现CompareTo方法的规范
和equals方法保持一致
使用compareTo方法有一个重要的约定,就是通常情况下compareTo方法施加的等同性测试和equals方法一致。如果不一致的话,集合接口一般是使用equals方法来进行等同性测试,而有序集合是采用compareTo方法进行等同性测试,如果两者不一致的话,容易造成灾难性的后果;
将对象与指定的对象进行比较,返回对应数字
在compareTo方法的前面就写好了实现compareTo方法所需要遵循的规则
当该对象小于、等于或者大于指定对象的时候,分别返回一个负整数,零或者正整数,如果由于指定对象的类型而无法与该对象进行比较,则抛出ClassCastException。在下面的说明中,符号sgn(表达式)表示数学中的signum函数,它根据表达式(expression)的值为负值、零和正值,分别返回-1、0、1。
一
必须确保所有的x和y都满足sgn(x.compareTo(y)) == -sgn(y.compareTo(x))。这也暗示着当且仅当y.compareTo(x)抛出异常时,x.compareTo(y)才抛出异常。
二
必须确保这个比较关系是可传递的:(x.compareTo(y) > 0 && y.compareTo(z) > 0)暗示着x.compareTo(z) > 0也成立。对应着equals使用规范里面的传递性。
三
必须确保x.compareTo(y) == 0暗示着所有的z都满足sgn(x.compareTo(z)) == sgn(y.compareTo(z))。
四
强烈建议(x.compareTo(y) == 0) == (x.equals(y)),但是这个并非绝对必要。一般来说,任何实现了Comparable接口的类,若违反了这个条件,都应该明确予以说明。推荐使用这样的说法:“注意,该类具有内在的排序功能,但是与equals不一致”。
比如BigDecimal的compareTo 和equals就有不同
BigDecimal t = new BigDecimal("1.0");
BigDecimal tt = new BigDecimal("1.00");
HashSet hs = new HashSet();
hs.add(t);
hs.add(tt);
TreeSet ts = new TreeSet();
ts.add(t);
ts.add(tt);
对于BigDecimal的equals来说,1.0和1.00不是同一个值
而对于BigDecimal的compareTo来说,1.0和1.00是同一个数。
如果一个类有多个关键域,那么比较这些关键域的顺序非常关键。从最关键的域开始进行比较,再比较所有的重要域。只要过程中比较产生了非零的结果(0代表着相等),则整个比较操作结束,并返回该结果。
结论
在实现Comparable接口时,上面的这些规范一定要遵守,否则可能造成严重后果而不自知。。。