如何正确比较 Java 中的两个整数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1514910/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to properly compare two Integers in Java?
提问by
I know that if you compare a boxed primitive Integer with a constant such as:
我知道,如果将装箱的原始 Integer 与常量进行比较,例如:
Integer a = 4;
if (a < 5)
a
will automatically be unboxed and the comparison will work.
a
将自动拆箱,比较将起作用。
However, what happens when you are comparing two boxed Integers
and want to compare either equality or less than/greater than?
但是,当您比较两个盒装Integers
并想要比较相等或小于/大于时会发生什么?
Integer a = 4;
Integer b = 5;
if (a == b)
Will above code result in checking to see if they are the same object, or will it auto-unbox in that case?
上面的代码会导致检查它们是否是同一个对象,还是在这种情况下会自动拆箱?
What about:
关于什么:
Integer a = 4;
Integer b = 5;
if (a < b)
?
?
回答by Adam Lewis
==
will still test object equality. It is easy to be fooled, however:
==
仍将测试对象相等性。然而,很容易被愚弄:
Integer a = 10;
Integer b = 10;
System.out.println(a == b); //prints true
Integer c = new Integer(10);
Integer d = new Integer(10);
System.out.println(c == d); //prints false
Your examples with inequalities will work since they are not defined on Objects. However, with the ==
comparison, object equality will still be checked. In this case, when you initialize the objects from a boxed primitive, the same object is used (for both a and b). This is an okay optimization since the primitive box classes are immutable.
您的不等式示例将起作用,因为它们未在对象上定义。但是,通过==
比较,仍将检查对象相等性。在这种情况下,当您从装箱基元初始化对象时,将使用相同的对象(对于 a 和 b)。这是一个不错的优化,因为原始框类是不可变的。
回答by Jon Skeet
No, == between Integer, Long etc will check for reference equality- i.e.
不,Integer、Long 等之间的 == 将检查引用相等性- 即
Integer x = ...;
Integer y = ...;
System.out.println(x == y);
this will check whether x
and y
refer to the same objectrather than equalobjects.
这将检查x
和是否y
引用相同的对象而不是相等的对象。
So
所以
Integer x = new Integer(10);
Integer y = new Integer(10);
System.out.println(x == y);
is guaranteed to print false
. Interning of "small" autoboxed values can lead to tricky results:
保证打印false
。“小”自动装箱值的实习可能会导致棘手的结果:
Integer x = 10;
Integer y = 10;
System.out.println(x == y);
This will print true
, due to the rules of boxing (JLS section 5.1.7). It's still reference equality being used, but the references genuinely areequal.
true
由于拳击规则(JLS 第 5.1.7 节),这将打印。它仍然参考平等使用,但引用真正的平等。
If the value p being boxed is an integer literal of type int between -128 and 127 inclusive (§3.10.1), or the boolean literal true or false (§3.10.3), or a character literal between '\u0000' and '\u007f' inclusive (§3.10.4), then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.
如果被装箱的值 p 是介于 -128 和 127 之间的 int 类型整数文字(第 3.10.1 节),或布尔文字 true 或 false(第 3.10.3 节),或介于 '\u0000' 和'\u007f' 包含(第 3.10.4 节),然后让 a 和 b 是 p 的任何两个装箱转换的结果。a == b 总是这样。
Personally I'd use:
我个人会使用:
if (x.intValue() == y.intValue())
or
或者
if (x.equals(y))
As you say, for any comparison between a wrapper type (Integer
, Long
etc) and a numeric type (int
, long
etc) the wrapper type value is unboxedand the test is applied to the primitive values involved.
如你说,对于一个包装型(之间的任何比较Integer
,Long
等)和数字类型(int
,long
等)的包装类型值是装箱和测试被施加到所涉及的原始值。
This occurs as part of binary numeric promotion (JLS section 5.6.2). Look at each individual operator's documentation to see whether it's applied. For example, from the docs for ==
and !=
(JLS 15.21.1):
这是作为二进制数字提升的一部分发生的(JLS 第 5.6.2 节)。查看每个操作员的文档,看看它是否被应用。例如,来自==
和!=
(JLS 15.21.1)的文档:
If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).
如果相等运算符的操作数都是数字类型,或者一个是数字类型而另一个可转换(第 5.1.8 节)为数字类型,则对操作数执行二进制数字提升(第 5.6.2 节)。
and for <
, <=
, >
and >=
(JLS 15.20.1)
和<
, <=
,>
和>=
( JLS 15.20.1)
The type of each of the operands of a numerical comparison operator must be a type that is convertible (§5.1.8) to a primitive numeric type, or a compile-time error occurs. Binary numeric promotion is performed on the operands (§5.6.2). If the promoted type of the operands is int or long, then signed integer comparison is performed; if this promoted type is float or double, then floating-point comparison is performed.
数值比较运算符的每个操作数的类型必须是可转换(第 5.1.8 节)为原始数值类型的类型,否则会发生编译时错误。对操作数执行二进制数字提升(第 5.6.2 节)。如果操作数的提升类型是 int 或 long,则进行有符号整数比较;如果此提升类型是 float 或 double,则执行浮点比较。
Note how none of this is considered as part of the situation where neithertype is a numeric type.
请注意,这些都不会被视为两种类型都不是数字类型的情况的一部分。
回答by Jon Skeet
tl;drmy opinion is to use a unary +
to trigger the unboxing on one of the operands when checking for value equality, and simply use the maths operators otherwise. Rationale follows:
tl; dr我的意见是+
在检查值相等时使用一元来触发对一个操作数的拆箱,否则只需使用数学运算符。原理如下:
It has been mentioned already that ==
comparison for Integer
is identity comparison, which is usually not what a programmer want, and that the aim is to do value comparison; still, I've done a little scienceabout how to do that comparison most efficiently, both in term of code compactness, correctness and speed.
前面已经提到,==
比较Integer
是身份比较,这通常不是程序员想要的,目的是做值比较;尽管如此,我还是做了一些关于如何最有效地进行比较的科学,无论是在代码紧凑性、正确性还是速度方面。
I used the usual bunch of methods:
我使用了通常的一堆方法:
public boolean method1() {
Integer i1 = 7, i2 = 5;
return i1.equals( i2 );
}
public boolean method2() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2.intValue();
}
public boolean method3() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2;
}
public boolean method4() {
Integer i1 = 7, i2 = 5;
return i1 == +i2;
}
public boolean method5() { // obviously not what we want..
Integer i1 = 7, i2 = 5;
return i1 == i2;
}
and got this code after compilation and decompilation:
并在编译和反编译后得到这段代码:
public boolean method1() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
return var1.equals( var2 );
}
public boolean method2() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method3() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method4() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method5() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2 == var1 ) {
return true;
} else {
return false;
}
}
As you can easily see, method 1 calls Integer.equals()
(obviously), methods 2-4 result in exactly the same code, unwrapping the values by means of .intValue()
and then comparing them directly, and method 5 just triggers an identity comparison, being the incorrect way to compare values.
正如你很容易看到的,方法 1 调用Integer.equals()
(显然),方法 2-4 产生完全相同的代码,通过解包值.intValue()
然后直接比较它们,方法 5 只是触发身份比较,这是不正确的方式比较值。
Since (as already mentioned by e.g. JS) equals()
incurs an overhead (it has to do instanceof
and an unchecked cast), methods 2-4 will work with exactly the same speed, noticingly better than method 1 when used in tight loops, since HotSpot is not likely to optimize out the casts & instanceof
.
由于(如 JS 已经提到的)equals()
会产生开销(它必须执行instanceof
且未经检查的强制转换),方法 2-4 将以完全相同的速度工作,在紧密循环中使用时明显优于方法 1,因为 HotSpot 不是可能会优化演员表 & instanceof
。
It's quite similar with other comparison operators (e.g. <
/>
) - they will trigger unboxing, while using compareTo()
won't - but this time, the operation is highly optimizable by HS since intValue()
is just a getter method (prime candidate to being optimized out).
它与其他比较运算符(例如<
/ >
)非常相似——它们会触发拆箱,而使用compareTo()
则不会——但这一次,HS 可以高度优化该操作,因为intValue()
它只是一个 getter 方法(被优化的主要候选者)。
In my opinion, the seldom used version 4 is the most concise way - every seasoned C/Java developer knows that unary plus is in most cases equal to cast to int
/.intValue()
- while it may be a little WTFmoment for some (mostly those who didn't use unary plus in their lifetime), it arguably shows the intent most clearly and most tersely - it shows that we want an int
value of one of the operands, forcing the other value to unbox as well. It is also unarguably most similar to the regular i1 == i2
comparison used for primitive int
values.
在我看来,将很少使用的版本4是最简洁的方式-每一个经验丰富的C / Java开发人员都知道,一元加在大多数情况下等于投地int
/ .intValue()
-虽然它可能是一个小WTF的某一时刻(主要是那些谁没't 在它们的生命周期中使用一元加号),它可以说是最清晰、最简洁地显示了意图 - 它表明我们想要一个int
操作数的值,迫使另一个值也取消装箱。毫无疑问,它i1 == i2
与用于原始int
值的常规比较最相似。
My vote goes for i1 == +i2
& i1 > i2
style for Integer
objects, both for performance & consistency reasons. It also makes the code portable to primitives without changing anything other than the type declaration. Using named methods seems like introducing semantic noise to me, similar to the much-criticized bigInt.add(10).multiply(-3)
style.
出于性能和一致性的原因,我投票支持对象i1 == +i2
和i1 > i2
风格Integer
。它还使代码可移植到原语,而无需更改除类型声明之外的任何内容。使用命名方法似乎给我带来了语义噪音,类似于备受批评的bigInt.add(10).multiply(-3)
风格。
回答by Cory Kendall
==
checks for reference equality, however when writing code like:
==
检查引用相等性,但是在编写如下代码时:
Integer a = 1;
Integer b = 1;
Java is smart enough to reuse the same immutable for a
and b
, so this is true: a == b
. Curious, I wrote a small example to show where java stops optimizing in this way:
Java是足够聪明,重新用于同一不变a
和b
,所以这是真的:a == b
。好奇,我写了一个小例子来说明java在哪里停止优化:
public class BoxingLol {
public static void main(String[] args) {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
Integer a = i;
Integer b = i;
if (a != b) {
System.out.println("Done: " + i);
System.exit(0);
}
}
System.out.println("Done, all values equal");
}
}
When I compile and run this (on my machine), I get:
当我编译并运行它(在我的机器上)时,我得到:
Done: 128
回答by otterslide
Calling
打电话
if (a == b)
Will work most of the time, but it's not guaranteed to always work, so do not use it.
大部分时间都会工作,但不能保证总是工作,所以不要使用它。
The most proper way to compare two Integer classes for equality, assuming they are named 'a' and 'b' is to call:
比较两个 Integer 类是否相等的最正确方法,假设它们被命名为 'a' 和 'b' 是调用:
if(a != null && a.equals(b)) {
System.out.println("They are equal");
}
You can also use this way which is slightly faster.
您也可以使用这种稍微快一点的方式。
if(a != null && b != null && (a.intValue() == b.intValue())) {
System.out.println("They are equal");
}
On my machine 99 billion operations took 47 seconds using the first method, and 46 seconds using the second method. You would need to be comparing billions of values to see any difference.
在我的机器上,990 亿次操作使用第一种方法需要 47 秒,使用第二种方法需要 46 秒。您需要比较数十亿个值才能看到任何差异。
Note that 'a' may be null since it's an Object. Comparing in this way will not cause a null pointer exception.
请注意,'a' 可能为空,因为它是一个对象。这样比较不会导致空指针异常。
For comparing greater and less than, use
要比较大于和小于,请使用
if (a != null && b!=null) {
int compareValue = a.compareTo(b);
if (compareValue > 0) {
System.out.println("a is greater than b");
} else if (compareValue < 0) {
System.out.println("b is greater than a");
} else {
System.out.println("a and b are equal");
}
} else {
System.out.println("a or b is null, cannot compare");
}
回答by Alex Torson
this method compares two Integer with null check, see tests
此方法将两个整数与空检查进行比较,请参阅测试
public static boolean compare(Integer int1, Integer int2) {
if(int1!=null) {
return int1.equals(int2);
} else {
return int2==null;
}
//inline version:
//return (int1!=null) ? int1.equals(int2) : int2==null;
}
//results:
System.out.println(compare(1,1)); //true
System.out.println(compare(0,1)); //false
System.out.println(compare(1,0)); //false
System.out.println(compare(null,0)); //false
System.out.println(compare(0,null)); //false
System.out.println(compare(null,null)); //true
回答by Justas
Since Java 1.7 you can use Objects.equals:
从 Java 1.7 开始,您可以使用Objects.equals:
java.util.Objects.equals(oneInteger, anotherInteger);
Returns true if the arguments are equal to each other and false otherwise. Consequently, if both arguments are null, true is returned and if exactly one argument is null, false is returned. Otherwise, equality is determined by using the equals method of the first argument.
如果参数彼此相等,则返回 true,否则返回 false。因此,如果两个参数都为 null,则返回 true,如果正好有一个参数为 null,则返回 false。否则,通过使用第一个参数的 equals 方法确定相等。
回答by HymanHammer
In my case I had to compare two Integer
s for equality where both of them could be null
. Searched similar topic, didn't found anything elegant for this. Came up with a simple utility functions.
在我的情况下,我必须比较两个Integer
s 的相等性,它们都可能是null
。搜索了类似的主题,没有找到任何优雅的东西。想出了一个简单的实用函数。
public static boolean integersEqual(Integer i1, Integer i2) {
if (i1 == null && i2 == null) {
return true;
}
if (i1 == null && i2 != null) {
return false;
}
if (i1 != null && i2 == null) {
return false;
}
return i1.intValue() == i2.intValue();
}
//considering null is less than not-null
public static int integersCompare(Integer i1, Integer i2) {
if (i1 == null && i2 == null) {
return 0;
}
if (i1 == null && i2 != null) {
return -1;
}
return i1.compareTo(i2);
}
回答by Chronoslog
Because comparaison method have to be done based on type int (x==y) or class Integer (x.equals(y)) with right operator
因为比较方法必须基于类型 int (x==y) 或类 Integer (x.equals(y)) 与正确的运算符
public class Example {
public static void main(String[] args) {
int[] arr = {-32735, -32735, -32700, -32645, -32645, -32560, -32560};
for(int j=1; j<arr.length-1; j++)
if((arr[j-1]!=arr[j]) && (arr[j]!=arr[j+1]))
System.out.println("int>"+arr[j]);
Integer[] I_arr = {-32735, -32735, -32700, -32645, -32645, -32560, -32560};
for(int j=1; j<I_arr.length-1; j++)
if((!I_arr[j-1].equals(I_arr[j])) && (!I_arr[j].equals(I_arr[j+1])))
System.out.println("Interger>"+I_arr[j]);
}
}
回答by Siyaram Malav
We should always go for equals() method for comparison for two integers.Its the recommended practice.
我们应该总是使用 equals() 方法来比较两个整数。这是推荐的做法。
If we compare two integers using == that would work for certain range of integer values (Integer from -128 to 127) due to JVM's internal optimisation.
如果我们使用 == 比较两个整数,由于 JVM 的内部优化,这将适用于特定范围的整数值(整数从 -128 到 127)。
Please see examples:
请看例子:
Case 1:
情况1:
Integer a = 100; Integer b = 100;
if (a == b) { System.out.println("a and b are equal"); } else { System.out.println("a and b are not equal"); }
整数 a = 100; 整数 b = 100;
if (a == b) { System.out.println("a and b are equal"); } else { System.out.println("a and b are not equal"); }
In above case JVM uses value of a and b from cached pool and return the same object instance(therefore memory address) of integer object and we get both are equal.Its an optimisation JVMdoes for certain range values.
在上述情况下,JVM 使用缓存池中 a 和 b 的值并返回整数对象的相同对象实例(因此是内存地址),我们得到两者相等。这是JVM针对某些范围值所做的优化。
Case 2:In this case, a and b are not equal because it does not come with the range from -128 to 127.
情况 2:在这种情况下,a 和 b 不相等,因为它不在 -128 到 127 的范围内。
Integer a = 220; Integer b = 220;
if (a == b) { System.out.println("a and b are equal"); } else { System.out.println("a and b are not equal"); }
整数 a = 220; 整数 b = 220;
if (a == b) { System.out.println("a and b are equal"); } else { System.out.println("a and b are not equal"); }
Proper way:
合适的方式:
Integer a = 200;
Integer b = 200;
System.out.println("a == b? " + a.equals(b)); // true
I hope this helps.
我希望这有帮助。