我试图对x和y点的集合进行排序,其中x的偏移使得p.x-q.x应该被视为等于IF p.x == q.x OR ABS(p.x-q.x)<偏移。 请注意,我在这里取绝对值,所以我不应该得到任何负值。我的比较器如下:
private static class XYOrder implements Comparator<ExtractPojo> {
public int compare(ExtractPojo p, ExtractPojo q) {
Integer a=p.x.intValue();
Integer b=q.x.intValue();
Integer c=p.y.intValue();
Integer d=q.y.intValue();
int offset=Math.abs(a-b); //calculate offset from x
if(offset < 15 || a == b) //if x is the same, sort by y coordinate
return c-d;
else return a-b; //if x is not same sort by x coordinate
}
}
此代码适用于某些情况,但我在其他情况下收到以下错误消息:
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
at java.util.TimSort.mergeForceCollapse(TimSort.java:426)
at java.util.TimSort.sort(TimSort.java:223)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
我有一种感觉,我违反了一个跨性别规则,因为我已经在这个网站上广泛搜索了答案,但我不确定如何测试我错过了什么这里。
我已经测试了没有偏移量的代码,但我没有收到此错误消息,所以我知道这与我实现偏移的方式有关。我已经试图解决这个问题几周而没有运气。
我希望得到一些关于此的提示或建议。非常感谢你。
所以我能想到的唯一解决方法是首先按x位置排序,然后遍历每个x并根据偏移量调整x&s,然后再按x,y进行排序上面提到没有偏移。看起来像是一个黑客,但我以前从未使用过比较器,而且我很难解决这个问题。
答案 0 :(得分:5)
确实你是。在你的比较器下,我们有我有一种感觉,我违反了过渡性规则
(0, 20) > (10, 10) > (20, 0) > (0, 20)
。 (另外,它拼写了&#34;及物性&#34;。)
通常,compare
,compareTo
和equals
方法不应使用公差,因为公差本质上是不敏感的。两个差异都低于容差,可能会超出容差。
答案 1 :(得分:0)
再次检查您的代码。这就是Java文档关于compare()
方法的实现所要说的。
当且仅当c.compare(e1,e2)== 0具有与e1.equals(e2)相同的布尔值时,比较器c对一组元素S施加的排序被认为与equals一致。对于S中的每个e1和e2。
您是否覆盖了equals()
课程的ExtractPojo
方法?您可以找到文档here。
此外,您不应该使用a == b
之类的代码。在这里,您有Integer
类型的变量。因此,它只会检查2个变量是否指向同一个对象(在这种情况下可能为false。更多关于here)。请改用a.equals(b)。
答案 2 :(得分:0)
所以我做了一些测试,我相信找到了你的问题:溢出。
我使你的比较方法变得非常简单,我仍然遇到了这个错误:
public int compare(ExtractPojo p, ExtractPojo q) {
Integer x1 = p.x.intValue();
Integer x2 = q.x.intValue();
return x1 - x2;
}
这是因为在某些情况下x1 - x2会导致溢出违反传递性。要检查这一点,请执行以下操作:
public int compare(ExtractPojo p, ExtractPojo q) {
Integer x1 = p.x.intValue();
Integer x2 = q.x.intValue();
checkSubtractionOverflow(x1, x2);
return x1 - x2;
}
//This will throw an exception if there is an overflow
public static void checkSubtractionOverflow(int left, int right) {
Math.subtractExact(left, right);
}
如果您看到异常:
Exception in thread "main" java.lang.ArithmeticException: integer overflow
at java.lang.Math.subtractExact(Unknown Source)
然后你知道你有溢出问题需要解决。
答案 3 :(得分:0)
基本上,您的代码是这样说的:
我怀疑传染性问题会受到影响,例如:
此外,您正在使用.intValue()
来电进行一些不必要的装箱/拆箱。 Integer a = P.x
是Integer to Integer赋值。