如何正确比较java中的两个整数?

ffvjumwh  于 2021-06-29  发布在  Java
关注(0)|答案(10)|浏览(300)

我知道如果你把一个装箱的基本整数和一个常量比较,比如:

Integer a = 4;
if (a < 5)
``` `a` 将自动取消装箱,比较将工作。
然而,当你比较两个盒子时会发生什么 `Integers` 想要比较相等还是小于/大于?

Integer a = 4;
Integer b = 5;

if (a == b)

上面的代码会导致检查它们是否是同一个对象,或者在这种情况下会自动取消装箱吗?
关于:

Integer a = 4;
Integer b = 5;

if (a < b)

?
gmol1639

gmol16391#

热释光;我的意见是用一元数 + 在检查值是否相等时触发其中一个操作数的解装箱,否则只需使用数学运算符。基本原理如下:
已经提到过 == 比较 Integer 身份比较,这通常不是程序员想要的,目的是做价值比较;尽管如此,我还是做了一些关于如何最有效地进行比较的科学研究,包括代码紧凑性、正确性和速度。
我用了通常的方法:

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不太可能优化cast& instanceof .
它与其他比较运算符(例如。 < / > )-使用时会触发拆箱 compareTo() 不会-但这一次,操作是高度优化的hs自 intValue() 只是一个getter方法(要优化的主要候选方法)。
在我看来,很少使用的版本4是最简洁的方法——每一个经验丰富的c/java开发人员都知道,在大多数情况下,一元加号等于cast to int / .intValue() -虽然这对一些人来说可能是一个小小的wtf时刻(大部分是那些在有生之年没有使用一元加号的人),但可以说它最清楚、最简洁地表明了我们的意图——它表明我们想要一个 int 一个操作数的值,强制另一个值也取消装箱。毫无疑问,它也最类似于规则 i1 == i2 用于原语的比较 int 价值观。
我投你一票 i1 == +i2 & i1 > i2 的样式 Integer 对象,出于性能和一致性的考虑。它还使代码可移植到原语,而不必更改除类型声明以外的任何内容。使用命名方法似乎给我带来了语义噪音,类似于备受批评的方法 bigInt.add(10).multiply(-3) 风格。

hvvq6cgz

hvvq6cgz2#

因为比较方法必须基于类型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]);
    }
}
9vw9lbht

9vw9lbht3#

我们应该始终使用equals()方法来比较两个整数。这是推荐的做法。
如果我们使用==比较两个整数,由于jvm的内部优化,这将适用于特定范围的整数值(从-128到127的整数)。
请参见示例:
案例1:
整数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");
}

在上面的例子中,jvm使用缓存池中的a和b的值,并返回integer对象的相同对象示例(因此内存地址),我们得到两者相等。这是jvm对某些范围值所做的优化。
案例2:在本例中,a和b不相等,因为它的范围不在-128到127之间。
整数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");
}

正确的方法:

Integer a = 200;             
Integer b = 200;  
System.out.println("a == b? " + a.equals(b)); // true

我希望这有帮助。

9bfwbjaz

9bfwbjaz4#

否,==between integer,long等将检查引用相等性-即。

Integer x = ...;
Integer y = ...;

System.out.println(x == y);

这将检查 x 以及 y 指的是同一个对象而不是相等的对象。
所以

Integer x = new Integer(10);
Integer y = new Integer(10);

System.out.println(x == y);

保证打印 false . “小”自动装箱值的实习可能会导致棘手的结果:

Integer x = 10;
Integer y = 10;

System.out.println(x == y);

这将打印 true 根据拳击规则(jls第5.1.7节)。它仍然是引用相等,但是引用真正相等。
如果要装箱的值p是int类型的整数文本,介于-128和127之间(包括-128和127)(§3.10.1),或布尔文字真或假(§3.10.3),或介于“\u0000”和“\u007f”之间的字符文字(§3.10.4),然后让a和b是p的任意两个装箱转换的结果。通常情况是a==b。
我个人会使用:

if (x.intValue() == y.intValue())

if (x.equals(y))

正如您所说,对于 Package 器类型之间的任何比较( Integer , Long 等等)和数字类型( int , long etc)取消 Package 类型值的装箱,并将测试应用于所涉及的原语值。
这是二进制数字提升的一部分(jls第5.6.2节)。查看每个操作员的文档,看看是否应用了它。例如,从 == 以及 != (jls 15.21.1):
如果相等运算符的操作数都是数字类型,或者一个是数字类型,另一个是可转换的(§5.1.8)对于数字类型,对操作数执行二进制数字提升(§5.6.2).
以及 < , <= , > 以及 >= (jls 15.20.1)
数值比较运算符的每个操作数的类型必须是可转换的类型(§5.1.8),否则会发生编译时错误。对操作数执行二进制数字提升(§5.6.2). 如果操作数的提升类型是int或long,则执行有符号整数比较;如果此提升类型是float或double,则执行浮点比较。
请注意,在两种类型都不是数字类型的情况下,这些都不被视为一部分。

nxowjjhe

nxowjjhe5#

此方法使用空检查比较两个整数,请参阅测试

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
gijlo24d

gijlo24d6#

== 仍将测试对象相等。然而,很容易被愚弄:

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)。这是一个很好的优化,因为基本box类是不可变的。

oogrdqng

oogrdqng7#

== 但是,在编写以下代码时,检查引用是否相等:

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");
    }
}

当我编译并运行这个(在我的机器上)时,我得到:

Done: 128
mqkwyuun

mqkwyuun8#

在我的情况下,我不得不比较两个 Integer 在他们两个都可以平等的地方 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);
}
lstz6jyr

lstz6jyr9#

由于java 1.7,您可以使用objects.equals:

java.util.Objects.equals(oneInteger, anotherInteger);

如果参数彼此相等,则返回true,否则返回false。因此,如果两个参数都为null,则返回true;如果只有一个参数为null,则返回false。否则,通过使用第一个参数的equals方法来确定相等性。

polhcujo

polhcujo10#

打电话

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");
    }

在我的机器上,使用第一种方法990亿次操作花费了47秒,使用第二种方法花费了46秒。您需要比较数十亿个值才能看到任何差异。
请注意,“a”可能为空,因为它是一个对象。以这种方式进行比较不会导致空指针异常。
要比较大于和小于,请使用

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");
}

相关问题