6

假期回来:)带着问题。我正在阅读 ComparableDocumentation 中的 Comparable 接口 文档。我确实理解,我们使用可比较的,因为它将为我们提供排序和自然排序。在文档中,它被写成。

强烈建议(尽管不是必需的)自然排序与 equals 一致。之所以如此,是因为没有显式比较器的排序集(和排序映射)在与自然顺序与等于不一致的元素(或键)一起使用时表现“奇怪”。特别是,这样的排序集合(或排序映射)违反了集合(或映射)的一般合同,该合同是根据 equals 方法定义的。

Comparable如何与equals相关。Comparable 有 compareTo 方法,为什么需要和 equals 方法保持一致?我无法理解这个概念。

还引用消息来源,有人也可以详细说明这一点

例如,如果添加两个键 a 和 b 使得 (!a.equals(b) && a.compareTo(b) == 0) 到不使用显式比较器的排序集,则第二个添加操作返回 false (并且排序集的大小不会增加)因为从排序集的角度来看 a 和 b 是等价的。

谢谢。

4

3 回答 3

8

返回 0的语义compareTo是两个对象是相等的。在另一种方法中对相同关系进行另一种定义显然会导致多种麻烦,正如您的引用中所记录的那样:实现中的典型算法SortedSet依赖于compareTo,但Set接口的一般合同规定它不能包含两个是的对象equalscompareTo报告的前后不一致equals会导致这种情况。

于 2013-08-18T18:24:56.420 回答
4

简短回答:每当compareTo(a,b)返回0两个对象ab,a.equals(b)并且b.equals(a)应该是true, 反之亦然。

长答案:如Comparable文档中所述,Comparable强制执行总排序的实现。全序的属性之一是“反对称”:如果我们定义一个全序≤,那么:

如果 a ≤ b 且 b ≤ a 则 a = b

这表示为 的0返回值compareTo()

您引用的文本中提到的方法和类利用了此特征,以实现更正确和更有效的行为。

于 2013-08-18T18:23:48.680 回答
2

您可以在 Set 的文档中看到它:

请注意,如果要正确实现 {@code Set} 接口,集合维护的顺序(无论是否提供显式比较器)必须与 equals 一致。(参见 {@code Comparable} 或 {@code Comparator} 以获得 与 equals 一致的精确定义。) 这是因为 {@code Set} 接口是根据 {@code equals} 操作定义的,但是 { @code TreeSet} 实例使用其 {@code compareTo}(或 {@code compare})方法执行所有元素比较,因此从集合的角度来看,此方法认为相等的两个元素是相等的。集合的行为定义明确,即使它的顺序与equals不一致;它只是不遵守 {@code Set} 接口的一般合同。

于 2013-08-18T18:25:39.283 回答