1. hashCode()とequals()の役割
Javaでは、hashCode()メソッドとequals()メソッドを使用して、2つのオブジェクトが等しいかどうかを比較します。
2. hashCode()とequals()の違い
それらの違いは、パフォーマンスと信頼性の2つの観点から紹介されています。
1. equals()は比較機能を実現できるのに、なぜhashCode()なのか?
書き換えられたequals()でのequalsの比較は、一般に、より包括的で複雑であるため、信頼性は良好ですが、効率が低下します。ただし、比較にhashCode()を使用する場合は、ハッシュ値を生成するだけで済みます。比較のために。高効率。
2. hashCode()が非常に効率的であるのに、equals()はなぜですか?
hashCode()は完全に信頼できるわけではないため、異なるオブジェクトが同じハッシュコードを生成することがあります(ハッシュ値式の生成で問題が発生する可能性があります)。したがって、hashCode()はほとんどの場合信頼できるとしか言えず、絶対的に信頼できるとは言えません。結論を出すことができます
- equals()等しい2つのオブジェクトのhashCode()は等しくなければなりません。つまり、equals()との比較は絶対に信頼できます。
- hashCode()が等しい2つのオブジェクトのequals()は必ずしも等しいとは限りません。つまり、hashCode()は完全に信頼できるわけではありません。
3. hashCode()およびequals()の使用に関する注意
1.大量の高速比較が必要な場合、equals()を使用すると明らかに非効率的であるため、比較が必要な場合は常に、最初にhashCode()を使用して比較します(hashCode()が異なります。これは、2つのオブジェクトが完全に等しくないことを意味します(つまり、equals()を使用して再度比較する必要はありません)。hashCode()が同じ場合は、equals()を比較します。 ()も同じです。これは、2つのオブジェクトが実際に同じであることを意味します。これにより、効率が大幅に向上し、比較の絶対的な正確性が保証されます。
2.この種の大きくて高速なオブジェクト比較は、HashSet、HashMap、HashTableなどのハッシュコンテナで一般的に使用されます。たとえば、HashSet内のオブジェクトでオブジェクトを繰り返すことができない場合は、それぞれを比較する必要があります。オブジェクトは内部で追加されます。彼の比較ルールは上記のとおりです。最初にhashCode()、hashCode()が同じ場合は、equals()を使用して、hashCode()がすべて異なる場合は、異なる必要があることを確認します。比較の効率は非常に高いです。
3.ただし、hashCode()とequals()は基本クラスObjectのメソッドであり、equals()と同様に、ObjectのhashCode()は現在のオブジェクトのアドレスのみを返します。この場合、同じです。クラス、新しい2つのオブジェクト、メモリ内のアドレスが異なるため、hashCode()が異なるため、これは明らかに必要なものではないため、クラスのhashCode()メソッド、つまりクラスReturnを書き直す必要があります。 hashCode()の一意のハッシュ値。
class User{
int id;
String name;
public int hashCode(){
return id*name.hashCode();
}
}
このクラスを識別するのは内部変数numとnameであるため、これらに基づくハッシュ値をこのクラスの唯一のハッシュ値として返します。
したがって、オブジェクトをhashSetに入れて、hashSetの特性を利用したい場合(つまり、同じオブジェクトが含まれていない場合)、クラスのhashCode()メソッドとequals()メソッドを書き直す必要があります。 。String、Integerなどのクラスは、これら2つのメソッドを内部的に書き直しました。
もちろん、2つのオブジェクトが同じであるかどうかを比較したいだけの場合は、1つのequals()を書き直してから、equals()を使用して比較するだけです。
4.拡張
1.アリババの開発仕様では、次のことが明確に規定されています。
equalsが書き換えられる限り、hashCodeは書き換えられる必要があります。
Setは、hashCodeとequalsに基づいて判断される一意のオブジェクトを格納するため、Setに格納されているオブジェクトは、これら2つのメソッドを書き換える必要があります。
カスタムオブジェクトがマップのキーとして使用されている場合は、hashCodeとequalsを書き直す必要があります。
StringはhashCodeとequalsメソッドを書き換えるので、Stringオブジェクトをキーとして非常に楽しく使用できます。
2.いつ書き直す必要がありますか?
通常、hashCodeをオーバーロードする必要はありません。クラスをHashTable、HashMap、HashSetなどのハッシュ構造のコレクションに配置する必要がある場合にのみ、hashCodeがオーバーロードされます。
3.では、なぜhashCodeをオーバーロードするのでしょうか。
たとえば、オブジェクトのコンテンツに基づいてequalsを書き直し、hashCodeの実装を変更しない場合、2つのオブジェクトは明らかに「等しい」が、hashCodeは異なる可能性が非常に高くなります。
このように、それらの1つをキーとして使用してhashMap、hasoTable、またはhashSetに保存し、「equal」を使用してもう1つをキー値として使用してそれらを見つけると、まったく見つかりません。 。
例の説明が
印刷された値は次のとおりです。
1901116749
1807500377
355165777
1414159026
1569228633
778966024は、
我々は2 HashCodeClass等しいの前提は2 HashCodeClassのSTR0、dou0、およびINT0が等しいということであることを願っています。OK、それならこのクラスがhashCode()メソッドをオーバーライドしないという問題があります。
現在、私のHashCodeClassには初期値が割り当てられていないため、これらの6つのHashCodeClassはすべて等しいはずです。HashSetを例にとると、HashSet内のHashMapのテーブル自体のサイズは16であり、16を法とする6つのHashCodeはそれぞれ13、9、1、2、9、および8です。1つ目はテーブル[13]の位置に配置され、2つ目はテーブル[9]の位置に配置され、3つ目はテーブル[1]の位置に配置されます。。。しかし、明らかに等しいの6つのHashCodeClassがすべてありますが、これをどのように行うことができますか?HashSet自体に必要なのは、equalsオブジェクトが複製されないことです。これで、セットには5つのequalsオブジェクトが含まれます(計算された係数の2つが両方とも9であるため)。
だから何をすべきか?hashCodeメソッドを書き直して、str0、dou0、およびint0に基づいて可能な限り一意のアルゴリズムを生成し、str0、dou0、およびint0が等しい2つのHashCodeClassが同じHashCodeを持つようにします。これは書き直すための要件です。 equalsメソッドhashCodeメソッドの理由を書き直してみてください。
4. equals()が等しい、hashCodeが等しい、hashCodeが等しいのに、equalsが等しい必要がないのはなぜですか。
小さなメモリブロックはhashCodeに従ってアクセスされるため、hashCodeは等しくなければなりません。
HashMapは、キーのhashCodeがtrueと等しいことを比較するオブジェクトを取得します。
hashCodeが等しいが等しい理由は異なる可能性があります。たとえば、ObjectAとObjectBの両方に属性名がある場合、hashCodeは名前で計算されるため、hashCodeは同じですが、2つのオブジェクトのタイプが異なるため、equalsはfalseになります。 。
5.なぜhashCodeが必要なのですか?
小さなメモリブロックは、hashCodeを介してすばやく見つけることができます。
hashCodeを介した比較は、equalsメソッドよりも高速です。getの場合は、最初にhashCodeを比較します。hashCodeが異なる場合は、falseを直接返します。