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

时间:2009-03-03 23:37:54

标签: java sorting puzzle

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

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的两个参数形式。

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

6 个答案:

答案 0 :(得分: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);
    }
};

如果您确定差异不会“环绕”,则使用减法很好。例如,当有问题的数据被限制为非负数时。

答案 1 :(得分:15)

您无法使用减号来创建比较。当绝对差值超过Integer.MAX_VALUE时,你会溢出。

相反,请使用此算法:

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

我喜欢在图书馆中使用此功能来实现此目的。

答案 2 :(得分:5)

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

这需要返回正数,如MAX_VALUE&gt; MIN_VALUE但是打印-1

答案 3 :(得分:5)

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

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

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

如有疑问,请使用经过充分测试的图书馆。

答案 4 :(得分:3)

你扔在那里的是什么数字?如果你的数字足够大,你可以用整数的MIN / MAX值换行,最后就会搞得一团糟。

答案 5 :(得分:2)

如果a的值非常负,且b的值非常正,则答案将非常错误。

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

- MarkusQ