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
so1、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)