当前位置: 首页 > 知识库问答 >
问题:

排序多维数组时“比较方法违反常规约定”

陆俊迈
2023-03-14

我正在使用自定义比较器对二维数组进行排序,在某些情况下会出现以下错误:

java.lang.IllegalArgument异常:比较方法违反其一般契约!在行781,java.base/java.util.TimSort.mergeLo在行518,java.base/java.util.TimSort.mergeAt在行448,java.base/java.util.TimSort.mergeCollapse在行245,java.base/java.util.TimSort.sort在行1442,java.base/java.util.Arrays.sort

下面是引发此错误的代码

class Solution {
    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals, new SortComparator());
    }
}

class SortComparator implements Comparator<int[]> {
    public int compare(int []a, int []b) {
        if(a[0] < b[0]) {
            return -1;
        } else if(a[0] > b[0]) {
            return 1;
        } else {
            if(a[1] < b[1]) {
                return -1;
            } else {
                return 1;
            }
        }
    }
}

虽然当我使用下面的 SortComparator 类实现时一切正常:

class SortComparator implements Comparator<int[]> {
    public int compare(int []a, int []b) {
        if(a[0] < b[0]) {
            return -1;
        } else if(a[0] > b[0]) {
            return 1;
        } else {
            if(a[1] < b[1]) {
                return -1;
            } else if(a[1]> b[1]) {
                return 1;
            } else {
                return 0;
            }
        }
    }
}

我能知道第一次实现< code>SortComparator时抛出错误的原因吗?

共有1个答案

康弘义
2023-03-14

问题是您的第一个 SortComparator 实现永远不会返回 0

因此<code>SortComparator。compare(a,a)永远不能返回0,因为它是 实现的“通用合同”所要求的。

事实上,<code>SortComparator。compare(a,a)将返回1

实际的合同在javadoc中。它说的是:

符号sgn(表达式)指定1数学符号函数,根据表达式的值是负的、零的还是正的,它被定义为返回-1、0或1中的一个。

实现者必须确保所有 x 和 y 的 sgn(compare(x, y)) == -sgn(compare(y, x))。 (这意味着 compare(x, y) 必须抛出异常当且仅当 compare(y, x) 抛出异常。

[...]

当 x 和 y 是同一个对象时,sgn(compare(x, y)) == -sgn(compare(y, x)) 为真的唯一方法是,如果 -sgn(compare(x, x)) 对于所有 x 都是零。

1 - 吹毛求疵:我认为他们应该在这里使用“表示”而不是“指定”这个词。

 类似资料:
  • 我知道它已经被询问和回答了数百万次,但我仍然无法弄清楚为什么我在排序期间收到了违规。这是我的代码: 我收到了这个错误 有什么想法吗?

  • 首先,很抱歉再次就这个话题提问。我很清楚这里有很多问题和答案。我已经读了其中的一些,但我的问题是我仍然不知道我做错了什么。这是我的代码: 看来我只是瞎了眼,看不到我的错误,所以如果你们中有人能帮我解决这个问题,我将非常感谢。 编辑:我想做的是确定一条线在左上角有0/0坐标的坐标系中是上、下、最左还是最右。这些点是double类型的。下面是错误消息:

  • 从昨天开始,我的代码中出现了错误,我不知道为什么!我用谷歌搜索了很多,找到了这个堆栈帖子。 我使用这个功能按名称对用户进行排序并创建日期。这个功能已经工作了2年,现在我收到一个用户的错误,我不知道发生了什么变化。我试图检查我的数据是否有任何损坏,但找不到任何问题。 读完zhe Stack-Post后,我仍然没有完全理解问题出在哪里,或者我的项目发生了什么变化。

  • 以下几行: 返回以下异常:比较方法违反了其一般约定! 我知道这个异常通常是在没有正确实现比较方法时产生的,但是在我的例子中,它的实现是相当明显的: 正如您所看到的,目标是按照值的hashValue属性对值进行排序。 任何关于我做错了什么的想法/提示将不胜感激! 谢谢托马斯

  • 我已经检查了以前关于这个话题的帖子-这个和这个。尽管如此,我还是想不出在我下面给出的代码中违反合同的情况是如何发生的。 我使用它的方式如下: iterTypeScoreMap声明如下 映射(iterTypeScoreMap)在排序过程中可能会改变,这就是为什么我复制了一份列表,然后对它调用sort。 既然我使用的是Double的内置compareTo方法,那么这不应该考虑合同吗?另一件让调试变得困

  • 是的,我知道有很多问题与相同的问题,但我似乎真的找不到我的比较器有什么问题。 所以,这里是: 代码非常简单:我需要根据它们如何改变我的主要结构对一些对象进行排序,并且我首先想要最高值。 由于计算或对象的影响可能需要一些时间,我只是缓存值以便重用它们,因此在排序之前,我检查是否有缓存值或是否需要计算它。 一旦我计算出将< code>m1或< code>m2应用于我的结构的结果,我就将更改恢复。 你可