证明equals与compareTo齐头并进

bvd*_*vdb 1 java equals compareto comparable

这是写在所有的java像样的课程,如果你实现了Comparable接口,你应该(在大多数情况下)覆盖equals以匹配其行为的方法.

不幸的是,在我目前的组织中,人们试图说服我完全相反.我正在寻找最有说服力的代码示例,向他们展示将要发生的所有邪恶.

Rob*_*ock 5

如果您不重写该equals方法,它将从该类继承其行为Object。当且仅当指定对象不为 null 并且引用同一实例时,
此方法才返回。true

假设有以下类:

class VeryStupid implements Comparable
{
  public int x;

  @Override
  public int compareTo(VeryStupid o)
  {
    if (o != null)
      return (x - o.x);
    else
      return (1);
  }
}
Run Code Online (Sandbox Code Playgroud)

我们创建2个实例:

VeryStupid one = new VeryStupid();
VeryStupid two = new VeryStupid();
one.x = 3;
two.x = 3;
Run Code Online (Sandbox Code Playgroud)

调用one.compareTo(two)返回 0 表示实例相等,但调用one.equals(two)返回 false 表示它们不相等。
这是不一致的。


Mad*_*apu 5

我认为你可以通过展示可比较的javadoc来说明:

强烈建议(尽管不要求)自然排序与equals一致.这是因为没有显式比较器的有序集(和有序映射)在与自然顺序与equals不一致的元素(或键)一起使用时表现得"奇怪".特别是,这样的有序集(或有序映射)违反了集合(或映射)的一般契约,它是根据等于方法定义的.

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

因此,特别是对于SortedSet(和SortedMap),如果compareTo方法返回0,它假定它相等,并且即使equals方法返回false 也不会第二次添加该元素,并导致SortedSet javadoc中指定的混淆

请注意,如果有序集合要正确实现Set接口,则由有序集合维护的排序(无论是否提供显式比较器)必须与equals一致.(有关与equals一致的精确定义,请参阅Comparable接口或Comparator接口.)这是因为Set接口是根据equals操作定义的,但是有序集使用compareTo(或compare)方法执行所有元素比较因此,从排序集的角度来看,这种方法被认为相等的两个元素是相等的.即使排序与equals不一致,排序集的行为也是明确定义的; 它只是不遵守Set接口的一般合同.