如何在Java中正确比较两个整数?
我知道,如果将装箱的基本整数与常数进行比较,例如:如何在Java中正确比较两个整数?,java,integer,autoboxing,Java,Integer,Autoboxing,我知道,如果将装箱的基本整数与常数进行比较,例如: Integer a = 4; if (a < 5) 上面的代码会导致检查它们是否是同一个对象,或者在这种情况下会自动取消装箱吗 那么: Integer a = 4; Integer b = 5; if (a < b) 整数a=4; 整数b=5; if(ai2样式。它还使代码可移植到原语,而不改变除类型声明以外的任何内容。使用命名方法似乎给我带来了语义噪音,类似于备受批评的bigInt.add(10).multiply(-3)样
Integer a = 4;
if (a < 5)
上面的代码会导致检查它们是否是同一个对象,或者在这种情况下会自动取消装箱吗
那么:
Integer a = 4;
Integer b = 5;
if (a < b)
整数a=4;
整数b=5;
if(a
?
==
仍将测试对象是否相等。然而,很容易被愚弄:
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
你的不等式示例将有效,因为它们不是在对象上定义的。但是,通过
==
比较,仍将检查对象相等性。在这种情况下,当您从装箱原语初始化对象时,将使用相同的对象(对于a和b)。这是一个不错的优化,因为基本框类是不可变的。否,==between Integer,Long等将检查引用相等性-即
这将检查x
和y
是否引用相同的对象而不是相等的对象
所以
保证打印false
。“小”自动装箱值的实习可能会导致棘手的结果:
Integer x = 10;
Integer y = 10;
System.out.println(x == y);
由于装箱规则(),这将打印true
。它仍然使用引用相等,但引用真正相等
如果要装箱的值p是int类型的整数文本,则
-128和127(§3.10.1),或布尔文字真或假(§3.10.3),或介于“\u0000”和“\u007f”之间的字符文字
包含(§3.10.4),然后让a和b为任意两个装箱的结果
p。a==b总是这样
就我个人而言,我会使用:
if (x.intValue() == y.intValue())
或
正如您所说,对于包装类型(Integer
,Long
等)和数字类型(int
,Long
等)之间的任何比较,包装类型值将被取消装箱,测试将应用于所涉及的原始值
这是二进制数字升级()的一部分。查看每个操作员的文档,查看是否应用了该文档。例如,从==
和的文档中=代码>():
如果相等的操作数
运算符都是数字类型,或
一个是数字类型,另一个是数字类型
可转换(§5.1.8)为数字
类型,二进制数字升级为
对操作数执行(§5.6.2)
对于=
()
操作数的每个操作数的类型
数值比较运算符必须是
可转换为(§5.1.8)的类型
基本数字类型,或
发生编译时错误。二元的
数字升级是在
操作数(§5.6.2)。如果被提升
操作数的类型为int或long,
然后进行有符号整数比较
表演;如果此升级类型为
浮点或双精度,然后是浮点
进行比较
请注意,这两种类型都不是数字类型的情况下,如何不将其视为一部分。tl;dr我的意见是,在检查值相等性时,使用一元+
触发其中一个操作数的解装箱,否则只需使用数学运算符即可。理由如下:
已经提到,==
整数的比较是身份比较,这通常不是程序员想要的,目的是进行值比较;尽管如此,我还是做了一些关于如何最有效地进行比较的科学研究,包括代码紧凑性、正确性和速度
我使用了通常的一系列方法:
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;
}
经过编译和反编译后得到了这段代码:
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;
}
}
正如您很容易看到的,方法1调用Integer.equals()
(显然),方法2-4产生完全相同的代码,通过.intValue()
展开值,然后直接比较它们,方法5只是触发身份比较,这是比较值的不正确方式
由于(如JS所述)equals()
会产生开销(必须进行instanceof
和未检查的强制转换),方法2-4的工作速度完全相同,在紧密循环中使用时明显优于方法1,因为HotSpot不太可能优化强制转换&instanceof
它与其他比较运算符(例如,
)非常相似-它们将触发取消装箱,而使用compareTo()
则不会-但这一次,操作可由HS进行高度优化,因为intValue()
只是一种getter方法(要优化的主要候选方法)
在我看来,很少使用的版本4是最简洁的方式——每一位经验丰富的C/Java开发人员都知道,在大多数情况下,一元加成等于转换为int
/.intValue()
——而对于一些人(大多数是那些在有生之年没有使用一元加成的人)来说,这可能是一个小小的WTF时刻,可以说,它最清楚、最简洁地显示了意图——它表明我们需要其中一个操作数的int
值,同时强制另一个值取消装箱。毫无疑问,它与用于原语int
值的常规i1==i2
比较最为相似
出于性能和一致性原因,我投票支持Integer
对象的i1==+i2
和i1>i2
样式。它还使代码可移植到原语,而不改变除类型声明以外的任何内容。使用命名方法似乎给我带来了语义噪音,类似于备受批评的bigInt.add(10).multiply(-3)
样式。==
检查引用相等性,但是在编写以下代码时:
Integer a = 1;
Integer b = 1;
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");
}
}
召唤
if (a == b)
大多数情况下都能工作,但不能保证总是工作,所以不要使用它。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;
}
}
Integer a = 1;
Integer b = 1;
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");
}
}
Done: 128
if (a == b)
if(a != null && a.equals(b)) {
System.out.println("They are equal");
}
if(a != null && b != null && (a.intValue() == b.intValue())) {
System.out.println("They are equal");
}
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");
}
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
java.util.Objects.equals(oneInteger, anotherInteger);
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);
}
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]);
}
}
if (a == b) {
System.out.println("a and b are equal");
} else {
System.out.println("a and b are not equal");
}
if (a == b) {
System.out.println("a and b are equal");
} else {
System.out.println("a and b are not equal");
}
Integer a = 200;
Integer b = 200;
System.out.println("a == b? " + a.equals(b)); // true