在 Java 中何时实施可比较以及何时实施等于

when to implement comparable and when to implement equals in Java

在 Java 中,我应该何时实施 Comparable<Something> 与实施 equals 方法?我明白每次我实施 equals 我也必须实施 hash code.

编辑

根据我得到的答案如下:

是否可以安全地说,如果我实施 Comparable,那么我就不需要实施 equalshashCode?如:我用 equal 可以完成的任何事情都已经包含在 compareTo 中了?例如,我希望能够比较两个 BST 是否相等。为此实施 hashCode 似乎令人望而生畏;那么 comparable 就足够了吗?

如果您只需要比较它们是否相等(或将它们放在实际上相同的 HashMapHashSet 中),您只需要实现 equalshashcode.

如果您的对象有一个隐式顺序并且您打算对它们进行排序(或将它们放在有效排序的 TreeMapTreeSet 中),那么您必须实现 Comparable 或提供一个 Comparator.

您应该考虑何时使用该对象。 例如,如果在 TreeMap 和 TreeSet 中,那么您将需要 Comparable。同样在任何情况下,当您必须对元素(尤其是已排序的集合)进行排序时,实施 Comparable 是强制性的。在非常多的情况下,大多数情况下都需要重写 equals 和 hashcode。

Comparable 通常用于排序项目(如排序),equals 用于检查两个项目是否相等。您可以使用 comparable 来检查是否相等,但并非必须如此。来自docs、"It is strongly recommended (though not required) that natural orderings be consistent with equals"

根据 javadocs:

This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method. Lists (and arrays) of objects that implement this interface can be sorted automatically by Collections.sort (and Arrays.sort). Objects that implement this interface can be used as keys in a sorted map or as elements in a sorted set, without the need to specify a comparator.

The natural ordering for a class C is said to be consistent with equals if and only if e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2) for every e1 and e2 of class C. Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false

简而言之,equals()hashcode()用于比较相等而Comparable用于排序

如果更新 equals 方法,则应始终更新 hashCode,否则当他们尝试在 HashMap 或 HasSet 或类似集合(非常常用)中使用它时,您将为自己或他人设置一个陷阱。

仅当您使用的界面需要 Comparable 时才需要它。您可以实现它以用于排序和排序的集合,但在大多数情况下实际上并不需要它。另一种方法是将 Comparator 传递给排序或集合构造函数。例如,String class 有一个不区分大小写的 Comparator,它非常有用,无需创建自己的 String class(即 String 无法扩展。)

equals(和hashCode)用于相等性测试。 Comparable 接口也可用于相等性检查,但实际上它用于对元素进行排序或比较它们的顺序。

也就是说,equals 只处理相等性(类似于 ==!=),而 compareTo 允许您检查许多不同类型的不等式(类似于<<===>=>!=)。因此,如果您的 class 有某种部分或全部排序,您可能需要实施 Comparable.

compareToequals之间的关系在the javadocs for Comparable中简单提到:

It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact. The recommended language is "Note: this class has a natural ordering that is inconsistent with equals."

ComparableTreeSet to compare and sort anything you insert into it, and it is used by List#sort(null) 用来对列表进行排序。其他地方也会用到,但首先想到的就是这些。