ホームページ > テクノロジー周辺機器 > IT業界 > Javaのハッシュコードを正しく実装する方法

Javaのハッシュコードを正しく実装する方法

尊渡假赌尊渡假赌尊渡假赌
リリース: 2025-02-18 10:46:14
オリジナル
610 人が閲覧しました

SitePoint Explore The Java World:Java開発者に貢献するように招待します

How to Implement Java's hashCode Correctly

SitePointはコンテンツフィールドを拡大し続けており、近い将来にJavaに焦点を当てます。あなたが経験豊富なJava開発者であり、当社のJavaコンテンツに貢献したい場合は、お問い合わせください。

Java

でのequalsおよびhashCodeメソッドの正しい実装

クラスに

メソッドを実装しましたか?素晴らしい!ただし、equalsメソッドも実装する必要があります。それを正しく実装する理由と方法を理解しましょう。 キーポイント:hashCode

Javaでは、等しいオブジェクトには同じハッシュコードが必要です。したがって、

メソッドが書き換えられた場合、ハッシュベースのコレクションにオブジェクトを保存および取得することの正確性と一貫性を確保するために、一致する

実装を作成する必要があります。
  • を実装する場合、メソッドで使用されているのと同じフィールドを使用する必要があります。パフォーマンスの問題を引き起こす可能性があるため、可変フィールドやコレクションの使用を避けるようにしてください。 equals hashCodeハッシュコードはパフォーマンスの最適化に関連しているため、パフォーマンス分析が改善が必要であることを示さない限り、ハッシュにあまり努力しないでください。
  • ハッシュアルゴリズムを改善し、多数を乗数として使用することにより、ハッシュ衝突(2つの異なるオブジェクトに同じハッシュコードがあります)を減らすことができます。これにより、セット内のハッシュコードをより均等に配布し、ハッシュ競合の可能性を減らし、より高速なデータ取得を確保することになります。
  • 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引用ソースコード:

メソッドの一般的な合意は次のとおりです

hashCodeJavaアプリケーションの実行中に同じオブジェクトで複数回呼び出される場合は、オブジェクトの比較で使用されている情報が変更されていない場合、

メソッドは常に同じ整数を返す必要があります。この整数は、1つのアプリケーションの実行と同じアプリケーションのもう1つの実行の実行との間で一貫性がある必要はありません。
  • 2つのオブジェクトがhashCodeメソッドに従って等しい場合、equalsメソッドへの呼び出しは、2つのオブジェクトのそれぞれで同じ整数結果を生成する必要があります。
  • 2つのオブジェクトがequals(Object)メソッドに従って等しくない場合、異なる整数の結果を生成する必要がある2つのオブジェクトのhashCodeメソッドを呼び出す必要はありません。ただし、プログラマーは、不均等なオブジェクトの異なる整数結果を生成すると、ハッシュテーブルのパフォーマンスが向上する可能性があることを認識する必要があります。
  • equals(Object) hashCode最初のポイントは、
  • メソッドの一貫性属性を反映しており、2番目のポイントは上記の要件です。 3番目のポイントは、後で説明する重要な詳細を示しています。
実装

メソッド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");
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
入力データに特定のパターンがある場合、優れたハッシュアルゴリズムでさえ異常に頻繁に競合する可能性があることに注意してください。簡単な例として、ポイントのxおよびy座標を追加することにより、ポイントのハッシュ値を計算するとします。これは、直線f(x)= -xのポイントを頻繁に扱うことに気付くまでかなり良いように聞こえます。これは、これらすべてのポイントでx y == 0であることを意味します。対立、たくさん!

しかし、もう一度:パフォーマンス分析に問題が示されない限り、一般的なアルゴリズムを使用し、心配しないでください。

要約

ハッシュコードの計算は、等価を整数値に圧縮するようなものであることがわかりました。等しいオブジェクトは同じハッシュコードを持っている必要があります。パフォーマンスの理由で、同じハッシュと同じように少数の不均等なオブジェクトをできるだけ少ないことを共有することをお勧めします。コード。

これは、

メソッドが書き換えられた場合、

メソッドを常に書き直す必要があることを意味します。

実装equalsメソッド:hashCode

hashCodeメソッドで使用されているのと同じフィールド(またはそのサブセット)を使用します。

    可変フィールドを含めないことをお勧めします。
  • equalsコレクションの
  • メソッドを呼び出さないことを検討してください。
  • 入力データのパターンが逆でない限り、
  • 一般的なアルゴリズムを使用します。
  • hashCode
  • 覚えておいてください、
  • メソッドはパフォーマンスに関連しているため、パフォーマンス分析で必要であることが示されない限り、あまり多くのエネルギーを無駄にしないでください。
  • 正しい実装Java
メソッド(FAQ)

のFAQ hashCode javaの

メソッドの重要性は何ですか?

hashCodejavaのメソッドは、整数値を返す組み込み関数です。主に、ハッシュベースのコレクション(

hashCode()など)がオブジェクトをより効率的に保存および取得するために使用されます。

メソッドは、各オブジェクトが一意の識別子を持っていることを確認するために、

メソッドと組み合わせて動作します。これにより、特に大規模なコレクションでデータを迅速に取得し、それによりJavaアプリケーションのパフォーマンスが向上するのに役立ちます。 hashCode()

hashCode()メソッドはJavaでどのように機能しますか?

Javaのメソッドは、オブジェクトのメモリアドレスを表す整数値を生成することにより機能します。この値は、ハッシュベースのコレクション内のオブジェクトのインデックス番号として使用されます。オブジェクト上の

メソッドを呼び出すと、ハッシュアルゴリズムを使用してこの一意の整数を生成します。ただし、2つの異なるオブジェクトには、ハッシュ競合と呼ばれる同じhashCode()が同じである可能性があることに注意することが重要です。 hashCode() javaのhashCodeメソッドと

メソッドの間の慣習は何ですか?

Javaのequals()のメソッドとメソッドの間の規則は、相互作用を管理するために使用される一連のルールです。条約では、2つのオブジェクトがhashCode()メソッドに従って等しい場合、

メソッドへの呼び出しは、2つのオブジェクトのそれぞれで同じ整数結果を生成する必要があると述べています。これにより、ハッシュベースのコレクションにオブジェクトを保存および取得するときに、一貫性と精度が保証されます。

equals() javaでhashCode()メソッドを書き直す方法は? equals() hashCode()Javaメソッドの

を書き換えて、各オブジェクトの一意の整数を返す独自の実装を提供することが含まれます。これは、オブジェクトのインスタンス変数とプライム乗数を使用して実現できます。プライムナンバーは、セット内のハッシュコードを均等に配布するのに役立ち、それによりハッシュ衝突の可能性が減少します。

hashCode()ハッシュの競合とは何ですか?それを避ける方法は?

ハッシュ競合とは、2つの異なるオブジェクトに対して同じ整数を生成することを意味します。適切に処理されていない場合、これはデータの損失につながる可能性があります。ハッシュの競合を回避するために、ハッシュアルゴリズムを改善して、よりユニークな整数を生成できます。さらに、マルチプライヤーとしてより大きな素数を使用すると、セット内のハッシュコードをより均等に配布するのに役立ちます。 hashCode()

なぜ

メソッドを書き直す必要があるのですか?

書き換えhashCode()メソッドは、特に大規模なコレクションを扱う場合、Javaアプリケーションのパフォーマンスを改善できます。独自の実装を提供することにより、よりユニークで均等に分散したハッシュコードを生成し、ハッシュ競合の可能性を減らし、より速いデータ検索を確保することができます。

Javaでは、2つの不均等なオブジェクトに同じ

を持つことができますか? hashCode()

はい、Javaでは、2つの不均等なオブジェクトが同じ

を持つことができます。これはハッシュ競合と呼ばれます。ただし、ハッシュアルゴリズムを改善し、大規模な素数を乗数として使用することにより、この発生の可能性を減らすことができます。 hashCode()

メソッドを書き直さないとどうなりますか? hashCode

メソッドをオーバーライドしない場合、Javaはデフォルトの実装を使用しますが、各オブジェクトに一意のハッシュコードを提供できない場合があります。これにより、ハッシュベースのコレクションでのハッシュ競合やデータの検索が遅くなる可能性があります。 hashCode

hashCode()Javaアプリケーションのパフォーマンスを改善する方法は?

hashCode()メソッドは、各オブジェクトに一意の識別子を提供することにより、Javaアプリケーションのパフォーマンスを向上させます。これにより、コレクション全体を検索せずにオブジェクトのハッシュコードを使用してオブジェクトを直接見つけることができるため、ハッシュベースのコレクションでデータをより速く取得できます。

非ハッシュベースのコレクションでhashCode()メソッドを使用できますか?

hashCode()メソッドは主にハッシュベースのコレクションに使用されますが、非ハッシュベースのコレクションにも使用できます。ただし、非ハッシュベースのコレクションは、データストレージと検索のためにハッシュコードに依存していないため、利点はそれほど明白ではない場合があります。

以上がJavaのハッシュコードを正しく実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート