第12条:考虑实现Comparable接口
compareTo方法并没有在Object中声明。相反,它是Comparable接口中唯一的一个方法。compareTo方法不但允许进行简单的同等性比较,而且允许执行顺序比较,除此之外,它与Object的equals方法具有相似的特性,还是个涉及到泛型的方法。类实现了Comparable接口,就表明它的实例具有内在的排序关系(natural ordering)。给实现Comparable接口的对象数组进行排序,
只需要下面这一行代码:
Arrays.sort(a);
对于存储在集合中的Comparable对象进行搜索、计算极限值以及自动维护也是同样的简单。例如下面的程序依赖于String实现了Comparable接口,它去掉了命令行参数列表中的重复参数,并按字母表顺序打印出来了:
public class WordList {
public static void main(String[] args) {
Set<String> s = new TreeSet<>();
Collection.addAll(s, args);
System.out.println(s);
}
}
一旦类实现了Comparable接口,它就可以跟许多泛型算法(generic algorithm)以及依赖于该接口的集合实现(collection implementation)进行协作。你付出了很小的努力就可以获得非常强大的功能。事实上,Java平台类库中的所有值类(value classes)都实现了Comparable接口。如果你正在编写一个值类,它具有非常明显的内在排序关系,那就应该优先考虑实现这个接口:
public interface Comparable<T> {
int compareTo(T t);
}
实现Comparable接口 覆盖compareTo方法必须满足:
1 必须确保所有的x和y都满足sgn(x.compareTo(y)) == -sgn(y.compareTo(x))。这也暗示着当且仅当y.compareTo(x)抛出异常时,x.compareTo(y)才抛出异常。这条规则和equals使用规范里面的对称性类似。
2 必须确保这个比较关系是可传递的:(x.compareTo(y) > 0 && y.compareTo(z) > 0)暗示着x.compareTo(z) > 0也成立。对应着equals使用规范里面的传递性。
3 必须确保x.compareTo(y) == 0暗示着所有的z都满足sgn(x.compareTo(z)) == sgn(y.compareTo(z))。
4 强烈建议(x.compareTo(y) == 0) == (x.equals(y)),但是这个并非绝对必要。一般来说,任何实现了Comparable接口的类,若违反了这个条件,都应该明确予以说明。推荐使用这样的说法:“注意,该类具有内在的排序功能,但是与equals不一致”。