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

Tom*_*ine 17 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

private static final Comparator<Thing> reverse = new Comparator<Thing>() {
    public int compare(Thing a, Thing b) {
        return a.getValue() - b.getValue();
    }
};
Run Code Online (Sandbox Code Playgroud)

然后我使用两个参数形式Arrays.sort.

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

eri*_*son 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);
    }
};
Run Code Online (Sandbox Code Playgroud)

如果你确定差异不会"环绕",使用减法就可以了.例如,当有问题的值被约束为非负数时.


Jas*_*hen 15

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

相反,使用此算法:

int compareInts( int x, int y ) {
  if ( x < y ) return -1;
  if ( x > y ) return 1;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我喜欢在库中为此目的使用此功能.

  • @Tom:`Integer.valueOf(x).compareTo(y);` 是我能想到的最简洁的方法。奇怪的是 Double 有静态的 `compare()` 方法而其他数字类型没有。 (2认同)
  • @Grundlefleck:是的!但是我的方法当然要快得多,因为它不会创建一个新的`Integer`实例. (2认同)

Pet*_*rey 5

尝试

System.out.println(Integer.MAX_Value - Integer.MIN_VALUE);
Run Code Online (Sandbox Code Playgroud)

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


mus*_*pax 5

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

在这种情况下,您可以执行以下操作:

return Integer.valueOf(a.getValue()).compareTo(b.getValue())
Run Code Online (Sandbox Code Playgroud)

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

  • 那里的开销的一点(对于非小值)。 (4认同)