Java Integer compareTo()-为什么使用比较与减法?
我发现Java Integer compareTo()-为什么使用比较与减法?,java,optimization,integer,comparison,integer-overflow,Java,Optimization,Integer,Comparison,Integer Overflow,我发现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)); } 这是由于整数溢出造成的。当t
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));
}
这是由于整数溢出造成的。当
thisVal
非常大且另一个值为负值时,从前者中减去后者会产生大于thisVal
的结果,该值可能会溢出到负值范围。可能是为了避免溢出/下溢。减法“技巧”比较两个数值是不正确的强>
int a = -2000000000;
int b = 2000000000;
System.out.println(a - b);
// prints "294967296"
这里,a
,然而a-b
是正的
不要使用这个成语。它不起作用
此外,即使它确实有效,它也不会在性能上提供任何显著的改进,而且实际上可能会降低可读性成本
另见
- 谜题65:一个可疑的奇怪故事
这个难题有几个教训。最具体的是:不要使用基于减法的比较器,除非您确定值之间的差值永远不会大于Integer.MAX_值
。更一般地说,要小心int
溢出。另一个教训是,您应该避免使用“聪明”的代码。努力编写清晰、正确的代码,除非证明有必要,否则不要对其进行优化
简单地说,
int
类型不够大,无法存储两个任意int
值之间的差异。例如,15亿和-15亿之间的差值为30亿,但是int
不能保存大于21亿的值。除了溢出的内容外,您应该注意带减法的版本不会给出相同的结果
- 第一个compareTo版本返回三个可能值之一:-1、0或1
- 如果用减法替换最后一行,结果可以是任何整数值
public int compareTo(Integer anotherInteger) {
return sign(this.value - anotherInteger.valuel);
}
当我们很快就开始担心微观优化时,我们经常会遇到错误代码。从JDK 7开始,我们可以使用
整数。比较(thisVal,anotherVal)
而不是写出三元表达式。结果不一样是正确的。但他们不是必须的compareTo
只需返回负值、零值或正值,具体取决于此
和其他对象的排序顺序。看,它一点也没坏。如果你知道你正在比较的数字,你可能知道比较它们是安全的。即使不知道,只要((long)a-b)
就行了。虽然你是对的;它很少有用。@naiad仅仅执行((长)a-b)
没有帮助,因为您必须将结果转换回int
,因为这是比较器必须返回的结果,结果再次溢出。您必须对结果执行类似于Long.signum
的操作,正如您的评论所示,这很容易忘记。它甚至可能不会比Integer.compare更有效,JVM可能会从本质上处理这一点……是的,他们在这里所做的工作可能比检查溢出和alUse Guava ComparisonChain更有效。它非常方便thisVal
不需要很大thisVal
甚至可能是零,而另一个val可能是Integer.MIN\u值,并且您已经有了溢出。请注意,当然,它也可能是另一种情况,thisValue
非常小,而anotherVal
相当大,其距离超出int
值范围。
public int compareTo(Integer anotherInteger) {
return sign(this.value - anotherInteger.valuel);
}