Java の == 演算子、equals メソッド、および hashCode メソッド

1. == 演算子

== は Java の演算子で、2 つのオブジェクトを比較するために使用されますが、2 つのオブジェクトを比較する場合は、比較の種類に基づいて議論する必要があります。

1.1 基本データ型と基本データ型

== を使用して基本データ型を比較す​​る場合、特定の型に関係なく、サイズが直接比較されます。

short num1 = 20000;
int num2 = 20000;
System.out.println(num1 == num2); // Output: true

1.2 参照型と参照型

参照型はメモリ アドレスを比較するため、== を使用して同じ型の 2 つのオブジェクトを比較した結果は通常 false になります。

public class Test {
    public static void main(String[] args) {
        Obj o1 = new Obj();
        Obj o2 = new Obj();
        System.out.println(o1 == o2); // Output: false
    }
}

class Obj {}

ただし、すべての状況で false が返されるわけではありません。基本データ型の参照型には定数プール メカニズムがあり、それらが 2 つのオブジェクトであっても、同じメモリ空間を指します。つまり、同じオブジェクトのままです。

Integer num1 = 100, num2 = 100;
System.out.println(num1 == num2); // Output: true

詳細は「基本8種類とその包装形態」をご覧ください。

1.3 基本的なデータ型と参照型

基本データ型と参照型を比較す​​る場合、参照型が数値であれば比較可能ですが、それ以外の型は比較できず、エラーとなります。

Integer num1 = 200;
int num2 = 200;
System.out.println(num1 == num2); // Output: true

int num = 200;
String str = "123";
System.out.println(str == num); // Error: 二元运算符 '==' 的操作数类型错误

2. イコールメソッド

equals は Java 参照型の基本メソッドです。これをオーバーライドしないと、equals メソッドはデフォルトで 2 つのオブジェクトのメモリ アドレスを比較します。オーバーライド後は、特定の状況に応じて異なります。

String str1 = "1";
String str2 = "2";
System.out.println(str1.equals(str2)); // Output: false

2.1 等号メソッドと == 演算子の違い

  • == は演算子、equals はオブジェクトのメソッドです (したがって、基本的なデータ型はありません)。
  • == 基本データ型を比較す​​る場合は比較される値であり、オブジェクトを比較する場合はメモリ アドレスを比較します。
  • デフォルトでは、equals (オーバーライドされていない) は比較オブジェクトのメモリ アドレスであり、オーバーライド後は他のコンテンツになります (たとえば、String はオブジェクトによって表されるコンテンツの値です)。

3. hashCodeメソッド

HashCode は、ハッシュ テーブルの知識を必要とする非常に特別なメソッドです。ハッシュはハッシュとして翻訳されます。あらゆるオブジェクトを 16 進値にすばやく変換できるアルゴリズムです。異なるオブジェクト間では、ハッシュ アルゴリズムを通じて取得されたハッシュ値は、高い確率で同じにはなりません。同じになる確率は非常に低いです。このとき、「ハッシュ競合」と呼ばれる状況が発生します。ここでは詳細には触れずに、「ハッシュアルゴリズムの比較」を参照してください。詳細。

つまり、「ハッシュの衝突」がなければ、異なるオブジェクトの異なるハッシュ値を通じて、2つのオブジェクトが同じオブジェクトであるかどうかを判断できます。

String str1 = "1";
String str2 = "2";
System.out.println(str1.hashCode() == str2.hashCode()); // Output: false

もちろん、通常の状況では、「ハッシュの競合」が発生しないという保証はないため、上記の hashCode メソッドは使用しません。異なるオブジェクトのハッシュ値は同じである可能性がありますが、2 つのオブジェクトのハッシュ値の違いは、それらが異なる必要があることを意味します。したがって、ハッシュ値を使用して、2 つのオブジェクトが等しくないかどうかを判断できます。

4. 違いとつながり

4.1 相違点

== は通常、数値が等しいかどうかを判断するために使用され、equals は通常 2 つのオブジェクトが等しいかどうかを判断するために使用され、hashCode は通常 2 つのオブジェクトが等しくないかどうかを判断するために使用されます。

==は数値を比較するだけで最も速く判定できます。また、hashCodeメソッドなので、ハッシュ値の計算が非常に高速です。最後にequalsです。デフォルトでは、equalsは2つのオブジェクトのメモリアドレスを比較します。このプロセスは非常に高速です。より一般的な状況では、equals メソッドがオーバーライドされ、2 つの非数値型オブジェクトのプロパティ値を比較するため、最も遅くなります。

String str1 = "1";
String str2 = "1";
System.out.println(str1.equals(str2)); // Output: true

上記のコードでは、Java の組み込み参照型 String が、メモリ アドレスではなく 2 つの String オブジェクトの内容を比較する、equals メソッドをオーバーライドします。

4.2 連絡先

== は一般に、equals と hashCode とは何の関係もありませんが、ある観点から見ると、equals と hashCode の間に必然的な関係はありません。しかし、Java には、equals と hashCode をリンクするデータ構造、つまり HashMap とそのサブクラスが存在します。

HashMap のキーは重複できないため、キーは異なるオブジェクトでなければなりません。このとき、比較には計算が速い hashCode が使用されます。ハッシュ値が等しくない場合、2 つのオブジェクトは一致しません。等しい場合、これには 2 つの可能性があります。1 つの状況は、2 つのオブジェクトが実際に等しいということであり、もう 1 つの状況は、まれに「ハッシュ競合」現象が発生するというもので、その後は等しい側の番になります。今度は、判断する時です!このようにして、反復不可能なキーの問題は効率的かつ迅速に解決されます。

上記の HashMap の比較から、型をカスタマイズするときに、equals メソッドまたは hashCode メソッドを書き換える場合は、両方を同時に書き換えてください。これは、Java の組み込みデータ構造 HashMap がどちらかを決定するためであることもわかります。重要なのは、複製では両方を同時に呼び出す必要があるということです。

まとめると、次の表のようになります。

比較方法 == 演算子 イコールメソッド hashCodeメソッド
速度を比較する 速い デフォルトでは高速ですが、一般的には低速です 中くらい
比較値 数値 デフォルトはメモリアドレスで、通常はオブジェクト属性です。 ハッシュ値

4.3 古典的な問題

hashCode メソッドをオーバーライドした後で、equals メソッドを書き直す必要があるのはなぜですか? equals メソッドのみをオーバーライドし、hashCode メソッドをオーバーライドしない場合に問題は発生しますか? HashMapにはどのように反映されるのでしょうか?

HashMap ではキーを繰り返すことができない、つまりキーが異なるため、異なるオブジェクトが同じオブジェクトであるかどうかを判断する必要があります。この問題を解決するために、HashMapではオブジェクトのequalsメソッドとhashCodeメソッドの両方を呼び出して判定を行っています。判定用のソースコードの一部は以下のとおりです。

if (e.hash == hash &&
    ((k = e.key) == key || (key != null && key.equals(k))))
    return e;

hashCode メソッドと equals メソッドは両方とも 2 つのオブジェクトの比較に使用できますが、それらの間にはいくつかの違いがあります。

比較方法 イコールメソッド hashCodeメソッド
速度を比較する

デフォルトでは、メモリアドレスが比較されるため、高速に実行されます。

書き換え後は全体的に内容を比較するため速度が遅いです。

ハッシュ値を高速に計算
比較値 メモリアドレスまたはメモリ内容(属性) ハッシュ値

そのため、計算速度の速い hashCode を使って比較することで、ほとんどの問題は解決できますが、「ハッシュ競合」が発生する可能性があるため、これを解決するためには、equals メソッドも必要になります。

キーが繰り返されているかどうかを判断するには、equals メソッドと hashCode メソッドを同時に呼び出す必要があるため、定義したクラスで書き換えるときに両方を一緒に書き換える必要があります。quals メソッドのみをオーバーライドし、hashCode メソッドをオーバーライドしない場合、内容は同じでメモリ アドレスが異なる 2 つのオブジェクトが作成されて HashMap に保存されると、それらは 1 つのキーではなく 2 つのキーとして扱われ、他のエラーが発生します。 。

おすすめ

転載: blog.csdn.net/weixin_62651706/article/details/132274016
おすすめ