如果我向Comparator
提供非及物Collections.sort
会怎样?我可以遇到无限循环吗?
我写的一个小测试产生了一个输出,但我想确保总是这样。
问题在于,在某些情况下,我的比较器可以产生循环,在这种情况下,我只是想确保它不会遇到无限循环。我不关心实际结果。
答案 0 :(得分:7)
Java docs说你必须确保比较器是传递性的。如果您提供的比较器不符合要求,则所有投注均已关闭。它可能适用于给定的实现,但可能会在另一个实现中崩溃(C ++中的std::sort
)。
简而言之,即使是某些或其他例子,也不应该依赖它。
答案 1 :(得分:4)
由于Java 7 Collections.sort使用TimSort。使用非传递比较器在Java> = 7中进行排序将引发以下异常:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
答案 2 :(得分:3)
Collections.sort()基于mergesort。
一个mergesort整体上有一个O(logn)迭代,因为数组大小总是被分割,所以sort()应该结束,无论Comparator不是不可传递的,所以不会发生无限循环。
但是,结果列表的订单无法保证。
答案 3 :(得分:2)
在这种情况下,Collections.sort的行为取决于实现。 Java 6 SE实现使用Mergesort和Insertionsort的组合,它们都是非传递性比较器的确定性,但在Java 7中Timsort算法被使用,而其他实现可能使用Quicksort或其他东西,所以你不能确定它会适用于所有实施。
答案 4 :(得分:0)
首先,我建议你考虑一下比较 - 同情操作真的是等价关系。 如果你接受它不是,它必须 - 跟踪一些局部变量中的比较对象。 此局部变量可以比较对象或线程局部变量。 此变量可以是对比对象集。在 compare 方法调用内部检查是否访问了该对 - 如果为true,则确定要执行的操作。 但是开车去看看被访问过的一组对象 - 它应该包含像哈希或对象id这样的东西,因为你可以通过其他方式进入无限远。 并且还要考虑到在局部变量中存储比较对是内存消耗。