【发布时间】:2017-05-23 18:00:50
【问题描述】:
我在尝试对节点的数组列表进行排序时遇到此错误。我已经尝试了大多数解决方案,但在我的情况下它们都不起作用。
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:866)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:483)
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:406)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:213)
at java.util.Arrays.sort(Arrays.java:1312)
at java.util.Arrays.sort(Arrays.java:1506)
at java.util.ArrayList.sort(ArrayList.java:1454)
at j...
代码是
static class Node implements Comparable<Node>
{
int key;
int value;
int double_value;
public Node(int key , int value , int double_value)
{
this.key = key;
this.value = value;
this.double_value = double_value;
}
public int compareTo(Node node)
{
if(double_value < node.double_value)
return 1;
else if(double_value > node.double_value)
return -1;
return -1;
}
}
它适用于小输入,但当输入数量很大时,它会出现此错误。我还阅读了比较方法中的传递性规则,但我无法弄清楚它在这种情况下是如何应用的。
提前致谢。
【问题讨论】:
-
如果两个节点的值相等,则返回 -1,这意味着一个节点可以同时小于和大于另一个节点,具体取决于您比较的顺序。这确实违反了
Comparable.compareTo的合同(就此而言,也违反了常识)。对于比较双精度的简单情况,请改用Double.compare方法。 -
您的
compareTo永远不会返回0以表明它们是相同的,并且您还应该覆盖equals()以便两个拥有相同 double_valuen1.equals(n2)的节点返回 true。当您覆盖等于时,您还应该覆盖hashcode() -
请不要使用下划线!遵循 Java 命名约定并将
double_value替换为doubleValue。 -
标识符应该代表目的和角色,而不是(错误地)实现,并且应该根据 Java 命名约定进行拼写。
标签: java collections comparable