【问题标题】:Does Collections.sort() with custom comparator does compare(a,b) and compare(b,a) for every pair (a,b)带有自定义比较器的 Collections.sort() 是否对每对 (a,b) 进行比较 (a,b) 和比较 (b,a)
【发布时间】:2016-03-29 17:45:49
【问题描述】:

将 Collections.sort() 与自定义比较器一起使用时,我遇到了错误

java.lang.IllegalArgumentException: Comparison method violates its general contract!

在谷歌上搜索此错误后,我看到一些解释说如果comapare(a,b) 给我-1 并且compare(b,a) 也给我-1 那么我会看到这个错误。

我不明白为什么会发生两次比较?

【问题讨论】:

  • 修复比较器即可。弄清楚排序例程进行的compare 调用的确切顺序对您没有帮助;只要输出经过排序,排序就可以随意进行任何比较,并且不同的 Java 版本和实现会做不同的事情。
  • 我了解到我的比较器有问题。我只是想了解每对是否发生多次比较
  • 不可能每对都发生;那将是 O(n^2) 比较和 Collections.sort 是 O(n log n)。

标签: java collections comparator


【解决方案1】:

JavaDoc of Comparable's compareTo()

实施者必须确保所有 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) 抛出异常,y.compareTo(x) 也应该抛出异常。
  • 如果x > y,和y > z,那么x > z
  • 如果x.compareTo(y) == 0,那么x.compareTo(z)y.compareTo(z) 应该具有相同的符号。

简而言之:如果a == b,那么b == a。如果没有,你就违反了合同。

【讨论】:

    【解决方案2】:

    从 Java 1.8 开始,Collections.sort(..) 将工作移交给 List#sort(),后者将工作移交给 Arrays.sort(..),后者将工作移交给类 TimSortHere's a link to the API and code used for that algorithm.

    它相当混乱和复杂(有充分的理由 - 优化排序算法很重要),但只要说它从不保证(甚至建议)每对元素只比较一次就足够了。它保证最多 O(n*logn) 比较,但不保证它们将是唯一的比较。

    【讨论】:

      猜你喜欢
      • 2021-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多