Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 按(x,y)坐标和偏移量排序会违反比较器契约_Java_Sorting_Collections_Coordinate Systems - Fatal编程技术网

Java 按(x,y)坐标和偏移量排序会违反比较器契约

Java 按(x,y)坐标和偏移量排序会违反比较器契约,java,sorting,collections,coordinate-systems,Java,Sorting,Collections,Coordinate Systems,我试图对x和y点的集合进行排序,在x上有一个偏移量,这样当p.x==q.x或ABS(p.x-q.x)(10,10)>(20,0)>(0,20)。(还有,拼写为“及物性”。) 通常,compare、compareTo和equals方法不应使用公差,因为公差本质上是不及物性的。两个都低于公差的差异加起来可能等于高于公差的差异。所以我又做了一些测试,我相信发现了您的问题:溢出 我将您的比较方法变得非常简单,但仍然会出现以下错误: public int compare(ExtractPojo p, Ex

我试图对x和y点的集合进行排序,在x上有一个偏移量,这样当p.x==q.x或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

    }
}
我有一种感觉,我违反了一个短暂性规则,因为我已经在这个网站上广泛搜索了一个答案,但我不确定如何测试我在这里遗漏了什么

我在没有偏移量的情况下测试了这段代码,但没有得到这个错误消息,所以我知道这与我如何实现偏移量有关。几周来,我一直在努力解决这个问题,但运气不佳

我希望得到一些关于这方面的提示或建议。多谢各位


所以我能想到的唯一解决办法是首先按x位置排序,然后遍历每个x,根据偏移量调整x,使其相同,然后再按上面提到的x,y进行排序,没有偏移量。这样做看起来像是一种黑客行为,但我以前从未使用过比较器,我很难解决这个问题。

再次检查您的代码。这就是Java文档关于
compare()
方法实现的内容

比较器c对一组元素S施加的顺序称为与equals一致,当且仅当c.compare(e1,e2)==0具有与e1相同的布尔值。S中的每个e1和e2都具有equals(e2)


您是否为
ExtractPojo
类重写了
equals()
方法?你可以找到医生

另外,您不应该使用像
a==b
这样的代码。这里有
Integer
类型的变量。因此,它将只检查这两个变量是否指向同一个对象(在本例中,可能为false。更多信息)。使用a.equals(b)代替

我有一种感觉,我违反了瞬变性规则

你确实是。在您的比较器下,我们有
(0,20)>(10,10)>(20,0)>(0,20)
。(还有,拼写为“及物性”。)


通常,
compare
compareTo
equals
方法不应使用公差,因为公差本质上是不及物性的。两个都低于公差的差异加起来可能等于高于公差的差异。

所以我又做了一些测试,我相信发现了您的问题:溢出

我将您的比较方法变得非常简单,但仍然会出现以下错误:

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)

然后您就知道您有需要解决的溢出问题。

基本上,您的代码是这样说的:

  • 如果x坐标彼此在15个单位内,则使用y坐标进行比较
  • 如果x坐标彼此相差15个或更多单位,则使用x坐标进行比较
  • x坐标是相等的,因此可以在不影响当前问题的情况下移动到任意一侧
我怀疑传递性问题会受到影响,例如,当:

  • P.x在Q.x和P
  • Q.x在R.x和Q
  • P.x从R.x开始超过15个单位,P>R(因为P.x>R.x)

另外,您正在使用
.intValue()
调用执行一些不必要的装箱/拆箱操作
整数a=P.x
是一个整数对整数的赋值。

如果(偏移量<15 | | a==b)
a==b
表示
偏移量
为0,它包含在
<15
的条件中。给出一些这种失败的例子,我不能给出一个失败的例子,因为我正在分析大量文件,这就是为什么很难看到它在哪里爆炸。@VinceEmigh
mergeHi
不是由OP…user1803551实现的方法,如果我只使用条件if(offset<15)和remove(a==b),我还是遇到了同样的问题。我会尝试一下,不,我不是压倒一切的平等者。我会让你知道这是怎么回事。即使我只是使用原语而不是对象整数,它仍然会失败。你是否重写了
equals()
方法?对于您得到的异常,我能想到的可能原因是您的
equals()
方法和比较器的
compare()
方法中的相等概念不一致。例如,考虑代码< > < <代码>等于<代码> b>代码>(例如1000)。根据
compare()
方法的逻辑,它应该返回
0
(这意味着2个
ExtractPojo
对象是相等的)。但是由于您没有重写
equals()
方法,它将使用默认的
equals()
方法由
对象
类提供,当且仅当两个变量
a
b
引用同一对象时,此方法才返回true。确定。。用重写的
equals()
检查它。不工作:/user2357112指出的问题,我想你必须找到一个解决方案。user2357112,很抱歉拼写错误。你对我如何解决这个问题有什么建议吗?@Mac:选择一个不同的排序标准,避免比较到一个容差。可以将x值分组到存储箱中,并按存储箱进行比较。
Exception in thread "main" java.lang.ArithmeticException: integer overflow
at java.lang.Math.subtractExact(Unknown Source)