Javaで2つの整数を正しく比較する方法



Answers

==オブジェクトの等価性をテストします。 しかし、それはだまされやすい:

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の両方)。 これは、プリミティブボックスクラスが不変なので、大丈夫です。

Question

私はボックス化されたプリミティブIntegerを以下のような定数と比較すると知っています:

Integer a = 4;
if (a < 5)

aは自動的にアンボックスされ、比較が機能します。

しかし、ボックス化された2つのIntegersを比較して、等価かそれとも/より小さいかを比較したいときはどうなりますか?

Integer a = 4;
Integer b = 5;

if (a == b)

上記のコードは、それらが同じオブジェクトであるかどうかを確認する結果になるか、その場合は自動的にアンボックスされますか?

何について:

Integer a = 4;
Integer b = 5;

if (a < b)




tl;私の意見では、値の等しいかどうかをチェックするときに単項+を使用してオペランドの1つでunboxをトリガーし、それ以外の場合は単に演算子を使用することです。 理由は次のとおりです。

Integer比較はIDの比較ですが、通常はプログラマが望むものではなく、目的は値の比較を行うことです。 それでも、コードのコンパクトさ、正確さ、スピードの両方の点で、この比較を最も効率的に行う方法について少しの科学を行ってきました。

私は通常の方法の束を使いました:

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().intValue()て値をアンラッピングして直接比較し、メソッド5はトリガーしますアイデンティティの比較。値を比較する不正な方法です。

(例えばJSですでに述べたように) equals()はオーバーヘッドを引き起こすので( instanceofと未チェックのキャストを行う必要がありinstanceof )、メソッド2-4は厳密に同じ速度で動作します。タイトなループで使用された場合、 HotSpotはキャストとinstanceofを最適化する可能性が低いためです。

compareTo()は使用しませんが、 intValue()intValue()がgetterメソッド(プライムintValue()にすぎないため、この操作はHSによって非常に最適化されます。候補者は最適化されています)。

私の意見では、めったに使用されないバージョン4は最も簡潔な方法です - すべての.intValue() C / Java開発者は、ほとんどの場合、 int / .intValue()にキャストすることと同等であることを知っています。 (主に一生の間に単項プラスを使用していなかった人たち)、それは間違いなくもっとも明確に、最も簡潔に意図を示しています - それは、オペランドの1つのint値が必要であることを示しています。 これはまた、原始的なint値に使用される通常のi1 == i2比較とは大して似ています。

私のi1 == +i2は、パフォーマンスと一貫性の理由からIntegerオブジェクトのi1 == +i2i1 > i2スタイルにIntegerます。 また、型宣言以外のものを変更することなく、コードをプリミティブに移植することもできます。 名前付きメソッドを使用すると、多くの批判を受けたbigInt.add(10).multiply(-3)スタイルに類似した意味的なノイズが私に導入されるようです。




Java 1.7以降、 Objects.equalsを使用できます:

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

引数が互いに等しい場合はtrueを返し、そうでない場合はfalseを返します。 したがって、両方の引数がnullの場合はtrueが返され、1つの引数がnullの場合はfalseが返されます。 それ以外の場合は、最初の引数のequalsメソッドを使用して等価を判定します。




Related