英文:
"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<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;
}
}
}
}
Although when I am using the below implementation of SortComparator
class everything works fine :
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;
}
}
}
}
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 中的一个值。
实现者必须确保对于所有 x
和 y
,sgn(compare(x, y)) == -sgn(compare(y, x))
。 (这意味着,如果且仅如果 compare(y, x)
抛出异常,compare(x, y)
必须抛出异常。)
[...]
当 x
和 y
是相同对象时,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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论