Java Integer compareTo() - 为啥使用比较与减法?

Posted

技术标签:

【中文标题】Java Integer compareTo() - 为啥使用比较与减法?【英文标题】:Java Integer compareTo() - why use comparison vs. subtraction?Java Integer compareTo() - 为什么使用比较与减法? 【发布时间】:2011-02-13 07:14:12 【问题描述】:

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

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

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

return thisVal - anotherVal;

【问题讨论】:

当我们急于担心微优化时,我们经常会遇到错误的代码。 从 JDK 7 开始,可以使用 Integer.compare(thisVal, anotherVal) 而不是写出三元表达式。 【参考方案1】:

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

【讨论】:

是的,他们在这里的做法可能比检查溢出等更有效 使用 Guava 比较链。它非常方便! google.github.io/guava/releases/22.0/api/docs/com/google/common/… thisVal 不需要很大。 thisVal 甚至可能为零,anotherVal 可能是 Integer.MIN_VALUE,而您已经溢出。请注意,当然,也可能是相反的情况,thisValue 非常小,anotherVal 相当大,距离超出 int 值范围。【参考方案2】:

比较两个数值的减法“技巧”被打破了!!!

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

这里,a &lt; b,但a - b 是肯定的。

不要使用这个成语。它不起作用。

此外,即使它确实有效,它不会提供任何显着的性能改进,实际上可能会降低可读性。

另见

Java Puzzlers 谜题 65:可疑的奇异传奇

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

【讨论】:

它并没有真正损坏。如果您对要比较的数字有所了解,您可能会知道比较它们是安全的。即使不知道,只是((long)a - b) 应该可以工作。虽然你是对的;它很少有用。 @naiad 只是做((long)a - b) 没有帮助,因为您必须将结果转换回int,因为这是比较器必须返回的内容,最终会再次溢出。正如您的评论所示,您必须对结果执行类似Long.signum 的操作,这很容易忘记。而且它甚至可能不比Integer.compare 更有效,JVM 可能会在本质上处理它......【参考方案3】:

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

【讨论】:

【参考方案4】:

也许是为了避免上溢/下溢。

【讨论】:

【参考方案5】:

除了溢出的东西,你应该注意,带减法的版本不会给出相同的结果

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

如果你知道不会溢出,你可以使用这样的东西:

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

【讨论】:

你说得对,结果不一样。但他们不是必须的! compareTo 只需要返回负值、零或正值,具体取决于this 和其他对象的排序顺序。见java.sun.com/j2se/1.5.0/docs/api/java/lang/…

以上是关于Java Integer compareTo() - 为啥使用比较与减法?的主要内容,如果未能解决你的问题,请参考以下文章

java TreeSet 倒序是怎么实现的?

java compareTo() 用法注意点

Java中的compareTo()函数是怎么用的?

java中comparator 接口怎么比较字符串?

Java Streams .max() 和 .min() 性能落后?

Integer源码分析