第12条:考虑实现Comparable接口

来源:互联网 发布:罗马音发音软件 编辑:程序博客网 时间:2024/05/21 19:36

第12条:考虑实现Comparable接口

如果一个类实现了Comparable接口,就代表着它的实例具有内在的排序关系。

先来看看Comparable接口:

public interface Comparable<T> {    public int compareTo(T o);}

可以看到,Comparable接口中只有compareTo一个方法,这个方法不但允许进行等同性比较,而且可以进行顺序比较。如果你正在编写一个具有明显内在排序关系的值类,那就应该坚决考虑实现这个接口。

compareTo方法的通用约定:

将这个对象与指定的对象相比较。当该对象小于,等于或大于指定对象时,分别返回一个负整数,零或正整数。如果由于指定对象的类型而无法与该对象进行比较,则抛出ClassCastException异常。

就如同违反了hashCode约定的类会破坏其它的依赖于散列的类一样(参照第9条),违反compareTo约定的类也会破坏其它带有排序关系的类,如TreeSet和TreeMap。

还有一点值得注意,书中强烈建议(x.compareTo(y)==0)==(x.equals(y)),因为如果不这么做,会导致这个类在不同的集合中有不同的表现。例如在BigDecimal类中:

BigDecimal bigDecimal1=new BigDecimal("1.0");BigDecimal bigDecimal2=new BigDecimal("1.00");System.out.println(bigDecimal1.equals(bigDecimal2));    //falseSystem.out.println(bigDecimal1.compareTo(bigDecimal2));     //0

由上可见在BigDecimal类中equals方法与compareTo方法表现不一致,若将这两个BigDecimal对象加入HashSet中,这个集合将包含两个元素,因为HashSet是基于equals方法的。但是将这两个对象加入TreeSet方法中,则在集合中只有一个元素,因为TreeSet是基于compareTo方法的。

如果一个类有多个应该比较的域,那么可以最重要的域开始,按照重要性由高到低逐步进行到所有需要比较的域。如果一个域中产生了非零的结果,则比较过程结束,直接返回该结果。若所有域中都相等,那么比较的两个对象就是相等的。例如:

public int compareTo(PhoneNumber pn) {    int areaCodeDiff = areaCode - pn.areaCode;    if (areaCodeDiff != 0){        return areaCodeDiff;    }    int prefixDiff = prefix - pn.prefix;    if(prefixDiff != 0){        return prefixDiff;    }    return lineNumber - pn.lineNumber;}

当这么做的时候,需要注意可能返回的最大和最小值应该在INTEGER.MAX_VALUE和INTEGER.MIN_VALUE之间,否则可能会产生溢出,返回错误的结果。

0 0
原创粉丝点击