Java Comparator:违反一般合同

Java Comparator:违反一般合同,java,Java,所以我有一个比较器: import java.util.Comparator; public class SolutionComparator implements Comparator<ExpressionTree> { private final int target; public SolutionComparator(int target) { this.target = target; } @Override p

所以我有一个比较器:

import java.util.Comparator;

public class SolutionComparator implements Comparator<ExpressionTree> {
    private final int target;

    public SolutionComparator(int target) {
        this.target = target;
    }

    @Override
    public int compare(ExpressionTree o1, ExpressionTree o2) {
        int v1 = o1.getValue();
        int v2 = o2.getValue();
        if (v1 == -1 && v2 == -1)
            return 0;
        else if (v1 == -1)
            return 1;
        else if (v2 == -1)
            return -1;
        else if (v1 == v2)
            return (int)Math.signum(solutionCost(o1) - solutionCost(o2));
        else
            return (int)Math.signum(Math.abs(target-v1) - Math.abs(target-v2));
    }

    private int solutionCost(ExpressionTree v) {
        int cost = 0;
        Operation o = v.getOperator();
        if (o != Operation.NONE) {
            cost += o.getCost();
            for (ExpressionTree e : v.getChildren())
                cost += solutionCost(e);
        }
        return cost;
    }
}

您的
比较器
违反了以下要求的平等传递性:

最后,实现者必须确保compare(x,y)==0意味着所有z的sgn(compare(x,z))==sgn(compare(y,z))

假设您有三个
ExpressionTree
s
o1、o2、o3
,分别具有相应的值
v1、v2、v3

和解决方案成本
s1、s2、s3

以至于
v1==v2

target-v1==v3-target
(因此
abs(target-v1)==abs(target-v3)


s1
(为了简单起见,
比较(o1,o2)=-1
,可以说是
o1

然后
o1==o3
o2==o3
但是
o1
,也就是说,
比较(o1,o3)==0

但是
sgn(比较(o1,o2))!=sgn(比较(o3,o2))


sgn(比较(o1,o2))=-1
sgn(比较(o3,o2))==0

我不知道你会怎么解决这个问题,但这是有原因的

编辑:@Nat(OP)想出了这个优雅的解决方案:

修复将替换
if(v1==v2)


if(Math.abs(target-v1)==Math.abs(target-v2))


你能发布整个异常跟踪吗?不久前我在这里遇到了完全相同的问题。这是一个平等的问题。我会尽力记住它是什么,然后回答你们。问题更新为异常跟踪。对于比较器,通常建议编写它们,以便比较(a,b)=-比较(b,a)。你的比较器可能会破坏这一点。一个简单的O(n^2)循环将为您找到这两个元素,然后您可以调试代码。solutionCost的结果是否为-2或更小?很好!我也终于明白了,但你比我快了几分钟:)非常感谢。对于那些感兴趣的人,修复方法是将
if(v1==v2)
替换为
if(Math.abs(target-v1==Math.abs(target-v2))
@Flavio谢谢。在很多问题上,第一个答案大约30秒就出来了,所以我期待着你随时给我独家报道。
Exception in thread "Thread-3" 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.mergeCollapse(TimSort.java:408)
    at java.util.TimSort.sort(TimSort.java:214)
    at java.util.TimSort.sort(TimSort.java:173)
    at java.util.Arrays.sort(Arrays.java:659)
    at java.util.Collections.sort(Collections.java:217)
    at ***.run(***:123)
    at java.lang.Thread.run(Thread.java:722)