Java 当我们总是从compare或compareTo方法返回相同的值时,Collections.sort的工作方式
考虑以下代码:Java 当我们总是从compare或compareTo方法返回相同的值时,Collections.sort的工作方式,java,collections,comparator,comparable,Java,Collections,Comparator,Comparable,考虑以下代码: 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() {
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);
}
}
从比较中返回固定值违反了合同。因此,结果是未定义的,并且依赖于实现 如果您想知道为什么在特定的实现中会得到某些结果,那么挖掘该实现以准确了解其工作原理是唯一的解决方案。您“幸运”了,
sort()
没有抛出IllegalArgumentException:Comparison方法违反了它的一般约定代码>
其所指的“总合同”记录在以下文件的javadoc中:
实施者必须确保所有x
和y
的sgn(x.compareTo(y))==-sgn(y.compareTo(x))
。(这意味着x.compareTo(y)
必须在y.compareTo(x)
引发异常时引发异常。)
实现者还必须确保关系是可传递的:(x.compareTo(y)>0和&y.compareTo(z)>0)
意味着x.compareTo(z)>0
最后,对于所有z
,实现者必须确保x.compareTo(y)==0
意味着sgn(x.compareTo(z))==sgn(y.compareTo(z))
你的代码违反了第一条规则
因此,排序的结果是未定义的。它工作得很差。它使用compareTo()
来确定列表的顺序。是的,我同意它工作得很差,但问题是为什么它总是以相反的顺序打印列表?回答得好。我会删除“幸运”部分——检查合同是否从未违反的额外复杂性——至少在这种情况下——不值得这么小的好处。在简单检查的情况下,如“参数不能为null”,检查足够简单,值足够高,值得实现。@ash我看到了这个错误。如果TimSort实现检测到compareTo
的结果不一致,它可能会抛出错误(因此“幸运”它没有抛出)。我指的不是那种应该做的事情,而是它已经做过的事情。参见源代码:有趣。我还没有深入研究这些内部结构。TimSort是否由Collections.sort()
使用?@ashCollections.sort()
调用List.sort()
调用Arrays.sort()
调用TimSort.sort()
(用于自然排序)或Comparator排序)或Arrays.mergeSort()
(如果系统属性java.util.Arrays.useLegacyMergeSort
为true
),那么通常是的(在java 11中)。这取决于观点。获得一个异常,并向您解释软件的错误,我称之为“幸运”,与得到一个未定义的结果相比,该结果甚至可能在测试期间看起来像预期的一样……几乎。总是返回零将在合同范围内。
Output is : [32, 67, 40]