【问题标题】:Contracts of the compare and compareTo method from Comparator and Comparable来自 Comparator 和 Comparable 的 compare 和 compareTo 方法的合同
【发布时间】:2015-02-10 03:28:30
【问题描述】:

在实现ComparatorComparable接口时,是否需要保证:

如果

  • x.compare(Object obj1, Object obj2) == x.compare(Object obj3, Object obj2)

  • obj1.compareTo(obj2) == obj3.compareTo(obj2),

那么obj1.equals(obj3) 必须是true

【问题讨论】:

    标签: java comparator comparable


    【解决方案1】:

    不一定。

    您所描述的是三个给定对象之间的transitive relation,而对于as far as both of the interfaces,使用它们时的关系必须在它们之间具有传递性。

    也就是说,给定三个类ABC,它们之间是可比较的,如果是A.compareTo(B) == 0 && B.compareTo(C) == 0,那么是A.compareTo(C) == 0。同样的原则也适用于Comparator

    您现在混淆的是compareToequals 之间的区别。虽然这两者密切相关,但文档中提供的very strong recommendation 没有任何强制要求:

    强烈建议,但不严格要求 (x.compareTo(y)==0) == (x.equals(y))。一般来说,任何实现Comparable接口并违反此条件的类都应该清楚地表明这一事实。推荐的语言是“注意:这个类有一个与equals不一致的自然顺序。”

    equals 定义与compareTo 甚至compare 不一致当然是可能且有效的,但根据程序的性质,它可能会导致难以理解的错误。如果您发现自己处于需要同时依赖equalscompareTo(或compare)的情况下,请记录下来并与它的用法保持一致。

    【讨论】:

      【解决方案2】:

      不,因为比较两个对象只能确定一个大于、等于或小于另一个。通常从比较器返回的结果是 (-1,0,1) 之一。例如:

      comparator.compare(1,5) == -1
      comparator.compare(1,3) == -1
      comparator.compare(3,1) == 1
      comparator.compare(5,3) == 1
      comparator.compare(3,3) == 0
      

      这使开发人员更容易在对象之间进行比较。如果合同要求返回差异的比例,那么对于字符串等实现这种方法将非常困难。为了获得精确的值差异,必须读取两个字符串的全部内容,这可能对性能非常不利,特别是如果这些字符串中的每一个都非常大。因为只需要确定哪个比另一个大,通常只需要比较字符串的一小部分来确定哪个比另一个“大”。唯一需要处理整个字符串的时间是它们实际上是否相等。这个性能问题也是为什么在可能的情况下首选哈希的原因

      【讨论】:

        最近更新 更多