SitePoint Explore The Java World:Java開発者に貢献するように招待します
Java
でのequals
およびhashCode
メソッドの正しい実装
メソッドを実装しましたか?素晴らしい!ただし、equals
メソッドも実装する必要があります。それを正しく実装する理由と方法を理解しましょう。
キーポイント:hashCode
メソッドが書き換えられた場合、ハッシュベースのコレクションにオブジェクトを保存および取得することの正確性と一貫性を確保するために、一致する
実装を作成する必要があります。equals
hashCode
ハッシュコードはパフォーマンスの最適化に関連しているため、パフォーマンス分析が改善が必要であることを示さない限り、ハッシュにあまり努力しないでください。 hashCode
equals
equals
ほとんどのデータ構造は、hashCode
メソッドを使用して、要素が含まれているかどうかを確認します。たとえば、
「b」のインスタンスは同じではないが(再び文字列のレジデンシーを無視する)、それらは等しいため、equals
変数hashCode
は真実です。
メソッドに渡すインスタンスと比較することは非効率的であり、データ構造のクラスはより効率的な方法を使用します。要求されたインスタンスを含む各要素と比較する代わりに、ショートカットを使用して、等しい可能性のあるインスタンスの数を減らし、それらのインスタンスのみを比較します。 equals
List<String> list = Arrays.asList("a", "b", "c"); boolean contains = list.contains("b");
contains
通常、次のように機能します:
contains
メソッドに渡すと、バケットはハッシュコードを使用して計算されます。その中の要素のみがインスタンスと比較されます。 メソッドを実装するには、理想的にはcontains
比較なしでは、非常に少数しか必要ありません。 equals
メソッドと同様に、equals
メソッドはhashCode
クラスでも定義されています。 Object
メソッドが平等を決定するためのショートカットとして使用されている場合、本当に気にするべきことは1つだけです。等しいオブジェクトには同じハッシュコードが必要です。 hashCode
これが、
実装を作成する必要がある理由でもあります。それ以外の場合、実装に応じて等しいものは、equals
クラスの実装を使用するため、同じハッシュコードを持たない場合があります。 hashCode
Object
hashCode
引用ソースコード:
メソッドの一般的な合意は次のとおりです実装メソッドは常に同じ整数を返す必要があります。この整数は、1つのアプリケーションの実行と同じアプリケーションのもう1つの実行の実行との間で一貫性がある必要はありません。
hashCode
Javaアプリケーションの実行中に同じオブジェクトで複数回呼び出される場合は、オブジェクトの比較で使用されている情報が変更されていない場合、
- 2つのオブジェクトが
hashCode
メソッドに従って等しい場合、equals
メソッドへの呼び出しは、2つのオブジェクトのそれぞれで同じ整数結果を生成する必要があります。- 2つのオブジェクトが
equals(Object)
メソッドに従って等しくない場合、異なる整数の結果を生成する必要がある2つのオブジェクトのhashCode
メソッドを呼び出す必要はありません。ただし、プログラマーは、不均等なオブジェクトの異なる整数結果を生成すると、ハッシュテーブルのパフォーマンスが向上する可能性があることを認識する必要があります。- メソッドの一貫性属性を反映しており、2番目のポイントは上記の要件です。 3番目のポイントは、後で説明する重要な詳細を示しています。
equals(Object)
hashCode
最初のポイントは、
メソッドequals
実装は次のとおりです
hashCode
に任されています。 Person.hashCode
List<String> list = Arrays.asList("a", "b", "c"); boolean contains = list.contains("b");
しかし、どのフィールドが関連していますか?これらの要件は、この質問に答えるのに役立ちます。等しいオブジェクトが同じハッシュコードを持っている必要がある場合、ハッシュコード計算には、平等チェックに使用されないフィールドを含めるべきではありません。 (それ以外の場合、これらのフィールドで異なる2つのオブジェクトのみが等しくなりますが、ハッシュコードが異なります。)
したがって、ハッシュに使用されるフィールドのセットは、平等に使用されるフィールドのセットのサブセットである必要があります。デフォルトでは、両方とも同じフィールドを使用しますが、考慮すべき詳細がいくつかあります。一貫性
まず、一貫性の要件があります。それは非常に厳密に解釈されるべきです。一部のフィールドが変更されたときにハッシュコードが変更されるようになりますが(これは、可変クラスでは避けられないことがよくあります)、ハッシュデータ構造はこのシナリオの準備ができていません。
上記のように、
ハッシュコードを使用して、要素のバケツを決定します。ただし、ハッシュ関連フィールドが変更された場合、ハッシュは再計算されず、内部配列は更新されません。これは、等しいオブジェクトを使用する、またはまったく同じインスタンスを使用することでさえ後続のクエリが失敗することを意味します!データ構造は、現在のハッシュコードを計算し(インスタンスを保存するために使用されるハッシュコードとは異なります)、間違ったバケットでそれを探します。
結論:ハッシュコード計算に可変フィールドを使用しないことが最善です!
パフォーマンス
ハッシュコードが計算される回数は、
メソッドが呼び出される回数とほぼ同じである場合があります。これは、コードの重要なパフォーマンス部分で発生する可能性が高いため、パフォーマンスを検討することは理にかなっています。また、メソッドとは異なり、ここには最適化の余地が増えます。 equals
equals
複雑なアルゴリズムが使用されていないか、多くのフィールドが関係していない限り、ハッシュコードを組み合わせる算術コストは避けられないコストと同じくらい些細なことです。ただし、すべてのフィールドを計算に含める必要があるかどうかを検討してください!特に、セットは懐疑的でなければなりません。たとえば、リストとコレクションは、各要素のハッシュ値を計算します。それらを呼び出す必要があるかどうかは、状況に基づいて考慮する必要があります。
を使用することも最良の選択ではない可能性があります。これは、その可変パラメーターの配列を作成する必要があるためです。
しかし、最適化に関する一般的なルールはまだ適用されます。早めに最適化しないでください!一般的なハッシュコードアルゴリズムを使用して、おそらくインクルージョンセットと最適化を放棄することは、パフォーマンス分析が改善の可能性があることを示した後にのみ行われます。 Objects.hash
パフォーマンスを追求するためのすべての努力をしてください。この実装はどうですか?
速くなければなりません。また、等しいオブジェクトには同じハッシュコードがあるため、この点でも問題ありません。ボーナスとして、変数フィールドは関係ありません!
List<String> list = Arrays.asList("a", "b", "c"); boolean contains = list.contains("b");
呼び出しは、リンクリストの線形スキャンをトリガーします。
したがって、同じバケツ内のアイテムの数を最小限に抑えたいと思います!非常に類似したオブジェクトでも非常に異なるハッシュコードを返すアルゴリズムは、良いスタートです。実装方法は、選択されたフィールドに一部依存します。計算に詳細を含めるほど、ハッシュコードが異なる可能性が大きくなります。これは、私たちがパフォーマンスについて考えていることの正反対であることに注意してください。したがって、あまりにも多くのまたは少ないフィールドを使用すると、パフォーマンスが低下する可能性があることに注意するのは興味深いことです。 競合を防ぐ別の部分は、実際にハッシュを計算するために使用されるアルゴリズムです。
ハッシュ値を計算します
フィールドハッシュコードを計算する最も簡単な方法は、
メソッドを呼び出すことです。それらは手動で結合することができます。一般的なアルゴリズムは、任意の数値で開始し、繰り返し別の数値(通常は小さな素数)を掛け、フィールドのハッシュを追加することです。
hashCode
これはオーバーフローを引き起こす可能性がありますが、これはJavaの例外を引き起こさないため、大きな問題はありません。
List<String> list = Arrays.asList("a", "b", "c"); boolean contains = list.contains("b");
しかし、もう一度:パフォーマンス分析に問題が示されない限り、一般的なアルゴリズムを使用し、心配しないでください。
要約
ハッシュコードの計算は、等価を整数値に圧縮するようなものであることがわかりました。等しいオブジェクトは同じハッシュコードを持っている必要があります。パフォーマンスの理由で、同じハッシュと同じように少数の不均等なオブジェクトをできるだけ少ないことを共有することをお勧めします。コード。
これは、
メソッドが書き換えられた場合、メソッドを常に書き直す必要があることを意味します。
実装equals
メソッド:hashCode
hashCode
メソッドで使用されているのと同じフィールド(またはそのサブセット)を使用します。
equals
コレクションのhashCode
のFAQ
hashCode
javaの
hashCode
javaの
hashCode()
など)がオブジェクトをより効率的に保存および取得するために使用されます。 メソッドと組み合わせて動作します。これにより、特に大規模なコレクションでデータを迅速に取得し、それによりJavaアプリケーションのパフォーマンスが向上するのに役立ちます。 hashCode()
hashCode()
メソッドはJavaでどのように機能しますか? メソッドを呼び出すと、ハッシュアルゴリズムを使用してこの一意の整数を生成します。ただし、2つの異なるオブジェクトには、ハッシュ競合と呼ばれる同じhashCode()
が同じである可能性があることに注意することが重要です。 hashCode()
javaのhashCode
メソッドと
equals()
hashCode()
メソッドに従って等しい場合、
equals()
javaでhashCode()
メソッドを書き直す方法は? equals()
hashCode()
Javaメソッドの
hashCode()
ハッシュの競合とは何ですか?それを避ける方法は? ハッシュ競合とは、2つの異なるオブジェクトに対して同じ整数を生成することを意味します。適切に処理されていない場合、これはデータの損失につながる可能性があります。ハッシュの競合を回避するために、ハッシュアルゴリズムを改善して、よりユニークな整数を生成できます。さらに、マルチプライヤーとしてより大きな素数を使用すると、セット内のハッシュコードをより均等に配布するのに役立ちます。 hashCode()
書き換えhashCode()
メソッドは、特に大規模なコレクションを扱う場合、Javaアプリケーションのパフォーマンスを改善できます。独自の実装を提供することにより、よりユニークで均等に分散したハッシュコードを生成し、ハッシュ競合の可能性を減らし、より速いデータ検索を確保することができます。
hashCode()
を持つことができます。これはハッシュ競合と呼ばれます。ただし、ハッシュアルゴリズムを改善し、大規模な素数を乗数として使用することにより、この発生の可能性を減らすことができます。 hashCode()
hashCode
メソッドをオーバーライドしない場合、Javaはデフォルトの実装を使用しますが、各オブジェクトに一意のハッシュコードを提供できない場合があります。これにより、ハッシュベースのコレクションでのハッシュ競合やデータの検索が遅くなる可能性があります。 hashCode
hashCode()
Javaアプリケーションのパフォーマンスを改善する方法は? hashCode()
メソッドは、各オブジェクトに一意の識別子を提供することにより、Javaアプリケーションのパフォーマンスを向上させます。これにより、コレクション全体を検索せずにオブジェクトのハッシュコードを使用してオブジェクトを直接見つけることができるため、ハッシュベースのコレクションでデータをより速く取得できます。
hashCode()
メソッドを使用できますか? hashCode()
メソッドは主にハッシュベースのコレクションに使用されますが、非ハッシュベースのコレクションにも使用できます。ただし、非ハッシュベースのコレクションは、データストレージと検索のためにハッシュコードに依存していないため、利点はそれほど明白ではない場合があります。
以上がJavaのハッシュコードを正しく実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。