Java Integer compareTo()-为什么要使用比较与减法?


80

我发现该方法的java.lang.Integer实现compareTo如下所示:

public int compareTo(Integer anotherInteger) {
    int thisVal = this.value;
    int anotherVal = anotherInteger.value;
    return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
}

问题是为什么使用比较而不是减法:

return thisVal - anotherVal;

27
当我们如此急于担心微优化时,我们通常会遇到错误的代码。
凯文·布兰里恩

从JDK 7开始,可以使用Integer.compare(thisVal, anotherVal)而不是写出三元表达式。
斯图尔特(Stuart)标记

Answers:


96

这是由于整数溢出。当thisVal非常大且anotherVal为负数时,则从前者中减去后者会产生大于thisVal可能溢出至负数范围的结果。


是的,他们在这里执行此操作的方式可能比检查溢出等方式更有效
rogerdpack 2011年


thisVal不需要很大。thisVal甚至可能为零,并且anotherVal可能Integer.MIN_VALUE已经是您溢出了。并且请注意,当然,也可能是相反的,thisValue非常小anotherVal甚至很大,距离超过了int值范围。
Holger

65

减去两个数值的减法“技巧”就坏了!!!

        int a = -2000000000;
        int b =  2000000000;
        System.out.println(a - b);
        // prints "294967296"

这里a < b,又a - b是积极的。

不要使用这个成语。没用

而且,即使它的工作,这将提供实际上成本可读性任何性能显著的改善,和五月。

也可以看看

  • Java Puzzlers Puzzle 65:可疑排序的奇怪传奇

    这个难题有几个教训。最具体的是:不要使用基于减法的比较器,除非您确保值之间的差异永远不会大于 Integer.MAX_VALUE。更普遍地,提防int溢出。另一个教训是,您应该避免使用“聪明”的代码。力求编写清晰,正确的代码,除非证明有必要,否则不要对其进行优化。


2
根本没有坏。如果您知道要比较的数字,则可能会知道比较是安全的。即使不知道,也((long)a - b)应该工作。虽然你是对的;它很少有用。
amara 2010年

4
@naiad只是这样((long)a - b)做没有帮助,因为您必须将结果强制返回给int,因为这是比较器必须返回的结果,并再次以溢出结束。Long.signum如注释所示,您将不得不对结果做类似的事情,而这很容易忘记。而且它甚至可能比Integer.compareJVM可能固有地处理的效率更高……
Holger

9

简单来说,int类型不足以存储两个任意int值之间的差异。例如,15亿和-15亿之间的差额是30亿,但int不能持有大于21亿的值。



1

除了溢出外,还应注意带减号的版本不会产生相同的结果

  • 第一个compareTo版本返回以下三个可能值之一:-1、0或1。
  • 如果用减法替换最后一行,则结果可以是任何整数值。

如果您知道不会有溢出,则可以使用以下方法:

public int compareTo(Integer anotherInteger) {
    return sign(this.value - anotherInteger.valuel);
}

12
您是正确的,结果是不一样的。但是它们不是必须的!compareTo仅需要返回负值,零或正值,这取决于this和另一个对象的排序顺序。见java.sun.com/j2se/1.5.0/docs/api/java/lang/...
基督教Semrau
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.