令我惊讶的是,Java有时可以为您检查比较器合同。
例如,当您编写一个不遵循传递性的订单关系时,您会得到
java.lang.IllegalArgumentException: Comparison method violates its general contract!
如何检查此类违规行为? Java如何实现它?
(如果您不知道我在说什么,请参阅this question)
答案 0 :(得分:2)
当你获得此异常时,你并没有具体说。我假设当您使用自己的Collections.sort
作为参数进行Comparator
来电时,您会收到此消息,因为我已经能够找到此错误在Java源代码中。
(TimSort是用于Collections.sort
)
如果Comparator
不一致(compare(a,b)
的结果与compare(b,a)
的结果不一致)或不稳定,则不会返回相同的结果输入,您将在TimSort
方法保留的临时状态中获得内部不一致。
该算法检测到此内部不一致并抛出异常:
772 } else if (len1 == 0) {
773 throw new IllegalArgumentException(
774 "Comparison method violates its general contract!");
775 }
注意当您的比较器违反合同时,无法保证您会收到此异常(这对比较器的单元测试来说很酷)。
您碰巧传递给Collections.sort
的特定调用的输入可能不正确,或者Comparator的不一致输出可能不会导致TimSort方法内部不一致。
在这种情况下,结果排序顺序仍然可能不正确,但您无法保证获得例外。
答案 1 :(得分:1)
当然,通过检查您的代码无法证明这一点!
针对特定输入和某些代码分支检测到违规。例如
if( compare(x,y)==0 && compare(y,x)!=0 )
throw IllegalArgumentException: Comparison method violates its general contract!
只需检查抛出异常的实际来源,例如http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/TimSort.java#772