如何在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