【问题标题】:Does sorting by a non transitive comparator "work"?按非传递比较器排序“工作”吗?
【发布时间】:2011-12-18 13:41:16
【问题描述】:

如果我将非传递 Comparator 提供给 Collections.sort 会发生什么?我会陷入无限循环吗?

我编写的一个小测试产生了一个输出,但我想确保始终如此。

问题是在某些情况下,我的比较器会产生循环,在这种情况下,我只想确保它不会陷入无限循环。我不在乎实际结果。

【问题讨论】:

  • 也许贴一些相关的代码?
  • 这是一个一般性问题,与特定代码无关 - 问题是如果我提供一个不传递给 Collections.sort 的比较器会发生什么
  • 未定义使用非传递 Comparator 的行为,因为非传递 Comparator 未正确实现。在实践中,我相当确定Collections.sort()不会在无限循环中运行,即使Comparator 已损坏。但规范中没有任何内容要求这种行为。

标签: java sorting comparator


【解决方案1】:

Java docs 说您必须确保您的比较器是可传递的。如果您提供的比较器不符合要求,则所有赌注都将失败。它可能适用于给定的实现,但可能会在另一个实现中严重崩溃(C++ 中的 std::sort 会)。

简而言之,您不应该依赖它来工作,即使它对某些或其他示例有用。

【讨论】:

  • 嗨,巴勃罗。很抱歉劫持评论,但我在这里问了一个问题:stackoverflow.com/questions/45599509/… 您显然已经面临我今天面临的问题,其中 C++ std::sort 与非传递比较器崩溃。我想知道你是否知道为什么?再次,很抱歉劫持了 6 年的评论,但关于这个主题的数据很少。
【解决方案2】:

由于 Java 7 Collections.sort 使用 TimSort。在 Java >= 7 中使用非传递比较器进行排序将引发以下异常:

java.lang.IllegalArgumentException: Comparison method violates its general contract!

【讨论】:

    【解决方案3】:

    Collections.sort() 基于mergesort

    一个合并排序有一个 O(logn) 的迭代,因为数组大小总是被划分,所以 sort() 应该结束,不管 Comparator 不是传递的,所以不会发生无限循环。

    但是,不能保证结果列表的顺序。

    【讨论】:

    • 这是一个很好的评论,但实施可能会更改,恕不另行通知...
    • 是的。它在 Java 7 中发生了变化。
    【解决方案4】:

    在这种情况下,Collections.sort 的行为取决于实现。 Java 6 SE 实现使用了 Mergesort 和 Insertionsort 的组合,它们都具有非传递比较器的确定性,但在 Java 7 中使用了 Timsort 算法,其他实现可能使用 Quicksort 或其他东西,所以你不能确定它会与所有实现一起工作。

    【讨论】:

      【解决方案5】:

      首先,我建议你考虑比较——同情操作真的是等价关系。 如果您接受它不是并且它必须是 - 在某个局部变量中跟踪比较对象。 这个局部变量可能是比较对象或线程局部变量。 这个变量可能是一组对象对比较。在 compare 方法调用中检查这对是否被访问 - 如果为真,决定做什么。 但是对 Set of objects 访问过 - 它应该真正包含 hash 或 object id 之类的东西,因为你可以通过其他方式去无穷大。 还要考虑到将比较对存储在局部变量中会消耗内存。

      【讨论】:

        猜你喜欢
        • 2022-01-19
        • 2014-06-25
        • 2011-06-05
        • 2017-04-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-21
        相关资源
        最近更新 更多