为什么我的简单比较器坏了?

我有一个课程,我已将其简化为:

final class Thing { private final int value; public Thing(int value) { this.value = value; } public int getValue() { return value; } @Override public String toString() { return Integer.toString(value); } } 

我想对这个东西的数组进行排序。 所以我创建了一个简单的copmarator:

 private static final Comparator reverse = new Comparator() { public int compare(Thing a, Thing b) { return a.getValue() - b.getValue(); } }; 

然后我使用Arrays.sort的两个参数forms。

这适用于我的测试用例,但有时它会以一个奇怪但可重复的顺序结束。 怎么会这样?

整数溢出…或更确切地说,下溢。

相反,做一个明确的比较:

 private static final Comparator reverse = new Comparator() { public int compare(Thing a, Thing b) { int av = a.getValue(), bv = b.getValue(); return (av == bv) ? 0 : ((av < bv) ? -1 : +1); } }; 

如果你确定差异不会“环绕”,使用减法就可以了。 例如,当所讨论的值被约束为非负值时。

您不能使用减号来创建比较。 当绝对差值超过Integer.MAX_VALUE时,您将溢出。

相反,使用此算法:

 int compareInts( int x, int y ) { if ( x < y ) return -1; if ( x > y ) return 1; return 0; } 

我喜欢在库中为此目的使用此function。

尝试

 System.out.println(Integer.MAX_Value - Integer.MIN_VALUE); 

这需要返回一个正数,如MAX_VALUE> MIN_VALUE,而是打印-1

在比较Java原语时,建议将它们转换为Object对应物并依赖于compareTo()方法。

在这种情况下,你可以这样做:

 return Integer.valueOf(a.getValue()).compareTo(b.getValue()) 

如有疑问,请使用经过良好测试的库。

你扔在那里的是什么数字? 如果您的数字足够大,您可以将整数的MIN / MAX值换行并最终陷入混乱。

如果一个值非常负,而且b的值非常正,你的答案就会非常错误。

IIRC,Int溢出在JVM中无声地环绕

– MarkusQ