【问题标题】:How Collections.sort works when we returns the same value always from compare or compareTo method当我们总是从 compare 或 compareTo 方法返回相同的值时,Collections.sort 如何工作
【发布时间】:2020-01-27 00:05:33
【问题描述】:

考虑下面的代码:

class Employee implements Comparable<Employee>{

    int id;

    public Employee(int i) {
        this.id=i;
    }

    @Override
    public int compareTo(Employee other) {
        return -1;
    }

    public String toString() {

        return String.valueOf(id);
    }   
}

public class S13_0 {
     public static void main(String[] args) {
         List<Employee> list=Arrays.asList(new Employee(40),new Employee(67),new Employee(32));
         Collections.sort(list);
         System.out.println(list);
    }
}

在这段代码中,我们只是使用 ID 为 [40,67,32] 的员工对象列表 并使员工具有可比性。 现在我已经知道可比性通常是如何起作用的。 但我只是想知道在这种情况下我们何时返回 -1(负整数值) 无论输入如何,排序方法如何应用于列表并打印列表 以相反的顺序。

Output is : [32, 67, 40]

【问题讨论】:

  • 效果不佳
  • 它使用compareTo() 来确定列表的顺序。
  • 是的,我同意它效果不佳,但问题是为什么它总是以相反的顺序打印列表?

标签: java collections comparator comparable


【解决方案1】:

你很“幸运”sort() 没有抛出 IllegalArgumentException: Comparison method violates its general contract!

它所指的“一般合同”记录在Comparable.compareTo(T o)的javadoc中:

实施者必须确保所有xysgn(x.compareTo(y)) == -sgn(y.compareTo(x))。 (这意味着x.compareTo(y) 必须在当且仅当 y.compareTo(x) 抛出异常时抛出异常。)

实现者还必须确保关系是可传递的:(x.compareTo(y)&gt;0 &amp;&amp; y.compareTo(z)&gt;0) 隐含 x.compareTo(z)&gt;0

最后,实现者必须确保x.compareTo(y)==0 暗示sgn(x.compareTo(z)) == sgn(y.compareTo(z)),对于所有z

您的代码违反了第一条规则。

因此,排序的结果是undefined

【讨论】:

  • 好答案。我会删除“幸运”部分——检查合同从未违反的额外复杂性——至少在这种情况下——不值得小小的好处。在简单检查的情况下,例如“argument must not be null”,检查足够简单,值足够高,值得实施。
  • @ash 我已经看到了那个错误。如果 TimSort 实现在compareTo 的结果中检测到不一致,则可能 抛出错误(因此“幸运”它没有)。我指的不是那种应该做的事情,而是它已经做的事情。见源代码:TimSort.java line 773
  • 有趣。我还没有深入研究这些内部结构。 Collections.sort() 使用 TimSort 吗?
  • @ash Collections.sort()调用List.sort()调用Arrays.sort()调用TimSort.sort()(用于自然排序)ComparableTimSort.sort()(用于比较器排序) 或Arrays.mergeSort() (如果系统属性java.util.Arrays.useLegacyMergeSorttrue,所以通常是(在Java 11 中)。
  • 这取决于观点。获得一个异常并清楚地向您解释您的软件的错误,这就是我所说的“幸运”,而不是在测试期间获得一个甚至可能看起来符合预期的未定义结果......
【解决方案2】:

从比较中返回一个固定值违反了约定。因此,结果是未定义的,并且依赖于实现。

如果您想知道为什么会在特定实施中获得某些结果,那么深入研究该实施以准确了解其工作原理是唯一的解决方案。

【讨论】:

  • 差不多。始终返回零将在合同范围内。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多