mirror of
https://github.com/Jueee/effective-Java.git
synced 2024-12-28 05:40:27 +08:00
42 lines
3.7 KiB
Markdown
42 lines
3.7 KiB
Markdown
|
## 考虑实现 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` 接口提供了一系列比较器方法。
|