“Comparison method violates general contract ” while sorting multi-dimensional array

huangapple go评论80阅读模式
英文:

"Comparison method violates general contract " while sorting multi dimensional array

问题

以下是翻译好的部分:

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

java.lang.IllegalArgumentException: Comparison method violates its general contract!
at line 781, java.base/java.util.TimSort.mergeLo
at line 518, java.base/java.util.TimSort.mergeAt
at line 448, java.base/java.util.TimSort.mergeCollapse
at line 245, java.base/java.util.TimSort.sort
at line 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;
            }
        }
    }
}

我能知道第一个SortComparator实现抛出错误的原因是什么吗?

英文:

I am sorting a 2-d array using custom comparator and getting the following error in some cases :

> java.lang.IllegalArgumentException: Comparison method violates its general contract!
at line 781, java.base/java.util.TimSort.mergeLo
at line 518, java.base/java.util.TimSort.mergeAt
at line 448, java.base/java.util.TimSort.mergeCollapse
at line 245, java.base/java.util.TimSort.sort
at line 1442, java.base/java.util.Arrays.sort

Below is the code that is throwing this error :

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

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

Although when I am using the below implementation of SortComparator class everything works fine :

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

Can I know because of what reason first implementation of SortComparator is throwing error ?

答案1

得分: 2

问题在于你的第一个 SortComparator 实现永远无法返回 0

因此,SortComparator.compare(a, a) 无法返回所需的 0,因为这是 Comparator 实现的“通用契约”。

实际上,SortComparator.compare(a, a) 将返回 1


实际契约在 javadoc 中有说明。它说:

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

实现者必须确保对于所有 xysgn(compare(x, y)) == -sgn(compare(y, x))。 (这意味着,如果且仅如果 compare(y, x) 抛出异常,compare(x, y) 必须抛出异常。)

[...]

xy 是相同对象时,sgn(compare(x, y)) == -sgn(compare(y, x)) 只有在对于所有 x 都是零时才能成立。


注解:

  • 小问题:我认为他们应该在这里使用“denotes”而不是“designates”这个词。
英文:

The problem is that your first SortComparator implementation can never return 0.

Therefore SortComparator.compare(a, a) cannot ever return 0 as it is required to do by "the general contract" for Comparator implementations.

In fact, SortComparator.compare(a, a) will return 1.


The actual contract is in the javadoc. What it says is:

> The notation sgn(expression) designates<sup>1</sup> the mathematical signum function, which is defined to return one of -1, 0, or 1 according to whether the value of expression is negative, zero or positive.
>
> The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y, x)) for all x and y. (This implies that compare(x, y) must throw an exception if and only if compare(y, x) throws an exception.)
>
> [...]

The only way that sgn(compare(x, y)) == -sgn(compare(y, x)) can be true when x and y are the same object is if -sgn(compare(x, x)) is zero for all x.


<sup>1 - Nitpick: I think they should have used the word "denotes" rather than "designates" here.</sup>

huangapple
  • 本文由 发表于 2020年10月11日 14:00:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/64301039.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定