17

我有一堂课,我已经简化为:

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<Thing> reverse = new Comparator<Thing>() {
    public int compare(Thing a, Thing b) {
        return a.getValue() - b.getValue();
    }
};

然后我使用Arrays.sort.

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

4

6 回答 6

20

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

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

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

如果您确定差异不会“环绕”,则可以使用减法。例如,当所讨论的值被限制为非负时。

于 2009-03-03T23:44:44.610 回答
15

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

相反,请使用此算法:

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

为此,我喜欢在库中使用此功能。

于 2009-03-03T23:43:45.907 回答
5

尝试

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

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

于 2009-03-04T07:08:01.940 回答
5

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

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

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

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

于 2009-03-04T07:59:44.110 回答
3

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

于 2009-03-03T23:44:33.130 回答
2

如果 a 的值非常负而 b 的值非常正,那么您的答案将是非常错误的。

IIRC,Int 溢出在 JVM 中静默环绕

——马库斯

于 2009-03-03T23:47:28.037 回答