これはJavaの非常に古典的な質問であり、インタビュー中によく尋ねられます。実際、多くの本や記事は、ハッシュコード()とequals()メソッドを過負荷にして、ハッシュマップでカスタムキーの検索を実現する必要があると述べています。ただし、なぜこれを行う必要があるのか、そしてこれを行わないことによってどのような結果が生じるかについての記事はほとんどないようです。そのため、説明するためにこの記事を書きます。
まず第一に、次の人クラスをキーとして直接使用してハッシュマップに保存するとどうなりますか?
public class person {private string id; public Person(string id){this.id = id; }} import java.util.hashmap; public class main {public static void main(string [] args){hashmap <person、string> map = new hashmap <person、string>(); map.put(new Person( "001")、 "Indundingea"); map.put(new person( "002")、 "linyin"); map.put(new Person( "003")、 "Henrylin"); map.put(new person( "003")、 "indundingsealy"); System.out.println(map.toString()); System.out.println(map.get(new person( "001"))); System.out.println(map.get(new person( "002"))); system.out.println(map.get(new person( "003"))); }}では、出力の結果は何ですか?
{person@6e4d4d5e = henrylin、person@275cea3 = infindingsea、person@15128ee5 = infindingsealy、person@4513098 = linyin} nullnullnullここには2つの問題があることがわかります。
1。追加プロセス中に、key = new person( "003")のキー値ペアを2回追加しました。期待すると、ハッシュマップにはそのような重要な値ペアが1つしかないはずです。キー(予想)は同じであるため、繰り返し追加しないでください。 value = "Induncessealy"が2回目に追加されたのは、元の値= "Henrylin"を置き換える必要があります。しかし、入力では、予想される状況は発生しなかったことがわかりましたが、HashmapにはValue = "Indungsealy"とvalue = "Henrylin"の2つの重要な価値ペアがあり、それらの重要な値はまだ異なりますが、それは明らかに間違っています。
2。値を取得するとき、3人のオブジェクトを使用して検索します。これらの3つのオブジェクトは、(予想)に保存したばかりの3つの重要な値と同じですが、検索は3つのnull値であり、これは明らかに間違っています。
したがって、正しい方法は実際に多くの場所で説明されています。 Personクラスは直接変更され、過負荷になり、ハッシュコードメソッドが過負荷になり、修正された人クラスは次のとおりです。
public class person {private string id; public Person(string id){this.id = id; } @Override public boolean equals(object o){if(this == o)return true; if(o == null || getClass()!= o.getClass())return false;人の人=(人)o; if(id!= null?!id.equals(person.id):person.id!= null)return false; trueを返します。 } @override public int hashcode(){return id!= null? id.hashcode():0; }}次に、上記の検査手順を再検討すると、結果は次のとおりです。
{person@ba31 = infindingsea、person@ba32 = linyin、person@ba33 = infindingsealy} indundingsealinyininfindingsealyご覧のとおり、指摘されたすべてのハイライトとエラーが修正されました。それで、なぜこれが起こっているのですか?
ハッシュマップでは、検索キーの比較の順序は次のとおりです。
1.オブジェクトのハッシュコードを計算して、テーブルに存在するかどうかを確認します。
2。対応するハッシュコードの位置のオブジェクトが現在のオブジェクトに等しいかどうかを確認します。
明らかに、最初のステップはHashCode()メソッドを使用することであり、2番目のステップはEquals()メソッドを使用することです。オーバーロードが実行されない場合、オブジェクトクラスのこれら2つのメソッドは、これら2つのステップでデフォルトで呼び出されます。オブジェクトでは、ハッシュコードの計算方法は、オブジェクトアドレスに基づいて計算されます。 2人のオブジェクトアドレス(「003」)は異なるため、ハッシュコードも異なります。当然、ハッシュマップはそれらを同じキーとして扱いません。同時に、オブジェクトのデフォルトの等しい()では、オブジェクトのアドレスに基づいて比較されます。当然、1人( "003")と別の人( "003")は等しくありません。
これを理解した後、HashCode()とメソッドの両方を過負荷にする必要がある理由を簡単に把握できます。
•HashCode()のオーバーロードは、同じキーに対して同じハッシュコードを取得するため、ハッシュマップを指定したキーに配置できるようにします。
•equals()は、キーに保存されている現在のオブジェクトとオブジェクトが等しいことをハッシュマップに表示するため、キーに対応するキー値ペアを本当に取得できるようにすることです。
別の詳細があります。 Personクラスでは、HashCode()メソッドの強調は次のとおりです。
@overridepublic int hashcode(){return id!= null? id.hashcode():0;}ここで困惑する可能性のあるポイントは、なぜ型文字列の変数のハッシュコードを個人クラスのハッシュコード値として使用できるのですか?新しい人のハッシュコード(新しい文字列( "003"))と新しい人(新しい文字列( "003"))は等しいですか?
次のコードの出力を見てみましょう。
system.out.println( "induntsea" .hashcode()); system.out.println( "induntsea" .hashcode()); system.out.println(new String( "induntingsea")。hashcode()); system.out.println(new string( "indundingea")。hashcode()); 728795174728795174728795174728795174
4つのステートメントの出力がすべて等しいことがわかります。文字列タイプがハッシュコード()を過負荷にして文字列のコンテンツに応じてハッシュコード値を返すことを推測することは非常に直感的で合理的です。そのため、同じコンテンツの文字列には同じハッシュコードがあります。
同時に、これも質問を示しています。HashCode()が等しいことがわかっているのに、比較のためにequals()を使用する必要があるのはなぜですか?これは、上記の例の状況を回避するためです。なぜなら、個人クラスのHashCode()メソッドの過負荷実装によれば、PersonクラスはHashコード値として文字列型メンバーIDのハッシュコード値を直接使用するからです。ただし、人( "003")と文字列( "003")が等しくないことは明らかです。したがって、Hashcode()が等しい場合、比較するために等しい()も必要です。
次の例は、上記の説明の証拠として使用できます。
System.out.println(new Person( "003")。hashcode()); // 47667System.out.println(new String( "003")。hashcode()); // 47667System.out.println(new Person( "003")。equals(new String( "003"))); // 間違い
上記の記事Javaは、カスタマイズされたクラスをハッシュマップの重要な例として使用しています。これは私があなたと共有するすべてのコンテンツです。私はそれがあなたに参照を与えることができることを願っています、そしてあなたがwulin.comをもっとサポートできることを願っています。