effective-Java/ch03所有对象的通用方法/14.考虑实现Comparable接口.md
2019-10-10 20:10:34 +08:00

42 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 考虑实现 Comparable 接口
`compareTo` 方法是 `Comparable` 接口中的唯一方法。
与 Object 类的 equals 方法在性质上是相似的,除了它允许在简单的相等比较之外的顺序比较,它是泛型的。
通过实现 `Comparable` 接口一个类表明它的实例有一个自然顺序natural ordering
对实现 `Comparable` 接口的对象数组排序非常简单,如下所示:
```java
Arrays.sort(a);
```
它很容易查找,计算极端数值,以及维护 `Comparable` 对象集合的自动排序。
**示例代码**[Item14Example01.java](MethodsCommonToAllObjects/src/main/java/com/jueee/item14/Item14Example01.java):依赖于 String 类实现了 `Comparable` 接口,去除命令行参数输入重复的字符串,并按照字母顺序排序。
### compareTo 方法的通用约定
`compareTo` 方法的通用约定与 `equals` 相似:
  将此对象与指定的对象按照排序进行比较。 返回值可能为负整数,零或正整数,因为此对象对应小于,等于或大于指定的对象。 如果指定对象的类型与此对象不能进行比较,则引发 `ClassCastException` 异常。
  下面的描述中,符号 sgn(expression) 表示数学中的 signum 函数,它根据表达式的值为负数、零、正数,对应返回-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`
- 最后,对于所有的 z实现类必须确保 `x.compareTo(y) == 0` 意味着 `sgn(x.compareTo(z)) == sgn(y.compareTo(z))`
- 强烈推荐 `(x.compareTo(y) == 0) == (x.equals(y))`,但不是必需的。 一般来说,任何实现了 `Comparable` 接口的类违反了这个条件都应该清楚地说明这个事实。 推荐的语言是「注意:这个类有一个自然顺序,与 `equals` 不一致」。
  与 `equals` 方法一样,不要被上述约定的数学特性所退缩。这个约定并不像看起来那么复杂。 与 `equals` 方法不同,`equals` 方法在所有对象上施加了全局等价关系,`compareTo` 不必跨越不同类型的对象:当遇到不同类型的对象时,`compareTo` 被允许抛出 `ClassCastException` 异常。 通常,这正是它所做的。 约定确实允许进行不同类型间比较,这种比较通常在由被比较的对象实现的接口中定义。
  正如一个违反 hashCode 约定的类可能会破坏依赖于哈希的其他类一样,违反 `compareTo` 约定的类可能会破坏依赖于比较的其他类。 依赖于比较的类,包括排序后的集合 `TreeSet` 和 TreeMap 类,以及包含搜索和排序算法的实用程序类 `Collections``Arrays`
### 比较类中的多个重要属性
如果一个类有多个重要的属性,那么比较他们的顺序是至关重要的。 从最重要的属性开始,逐步比较所有的重要属性。 如果比较结果不是零(零表示相等),则表示比较完成; 只是返回结果。 如果最重要的字段是相等的,比较下一个重要的属性,依此类推,直到找到不相等的属性或比较剩余不那么重要的属性。
**示例代码**[Item14Example02.java](MethodsCommonToAllObjects/src/main/java/com/jueee/item14/Item14Example02.java):依次比较判断。
**示例代码**[Item14Example03.java](MethodsCommonToAllObjects/src/main/java/com/jueee/item14/Item14Example03.java):使用 Java 8 中 `Comparator` 接口提供了一系列比较器方法。