私たちは皆、Java言語が完全にオブジェクト指向であることを知っています。 Javaでは、すべてのオブジェクトがオブジェクトクラスから継承されます。
Equalsメソッドは、2つのオブジェクトの参照によって指されたアドレスを比較します。ハッシュコードはローカルメソッドであり、オブジェクトアドレス値を返します。 OJBectクラスには2つの方法があり、ハッシュコードがあります。これらの2つの方法は、2つのオブジェクトが等しいかどうかを比較するために使用されます。
等しい方法を書き換えながら、ハッシュコードメソッドをオーバーライドする必要があるのはなぜですか?
次のように理解することができます。等方メソッドを書き換えた後、オブジェクトの平等を判断するためのビジネスロジックは変更されます。クラスのデザイナーは、メモリアドレスを比較して2つのオブジェクトの平等を比較したくありません。住所に従って比較し続けることは意味がありません。したがって、それは単に一緒に変更されます。
別の理由はコレクションから来ています。それについてゆっくりと以下で話しましょう〜
例えば:
学校では、この人が属しているかどうかを判断するのは学生IDを通じてです。
以下のコードのシナリオは学生レコードエントリ、学生番号123は学生Tomに割り当てられ、学生番号456は学生ジェリーに割り当てられ、学生番号123は誤ってリリーに割り当てられます。ただし、同じ学生番号は、学生のステータスを登録するプロセス中に発生しないでください。
状況要件に応じて、重複するオブジェクトを追加することはできず、ハッシュセットを介して実装できます。
パブリッククラステスト{public static void main(string [] args){desute stu = new Student(123、 "tom"); hashset <sudent> set = new hashset <>(); set.add(stu); set.add(new sudine(456、 "jerry")); set.add(new desutor = set); iterator( "); iterator); while(iterator.hasnext()){desute sustent = iterator.next(); System.out.println(desutent.getStunum() + "---" + sustent.getName());}}} name;}@overridepublic boolean equals(object obj){if(this == obj)return true; if(obj instanceof student){if(this.getstunum()==((desute)obj).getstunum()return true;} return false;}}}}出力は次のとおりです。
123 ---リリー
456 ---ジェリー
123 ---トム
出力に基づいて、学生番号123をリリーに割り当てることが再び成功することがわかりました。何が悪かったの?
ハッシュセットの追加方法を見てみましょう。
public boolean add(e e){return map.put(e、seprent)== null;}実際、ハッシュセットはハッシュマップを介して実装されるため、HashMapのPUTメソッドをトレースします。
public v put(k key、v value){if(table == empty_table){inflatetable(threshold);} if(key == null)return putfornullkey(value); int hash = hash(key); int i = indexfor(hash、table.length); Hash &&((k = e.key)== key || key.equals(k))){v oldvalue = e.value = value; e.recordaccess(this); return oldvalue;}} modcount ++; addentry(hash、key、value、i); return null;};};1。キーによれば、つまり、ハッシュセットによって追加されるオブジェクト、ハッシュコードを取得し、ハッシュコードを使用して特定のビット操作を実行してハッシュコードを取得します。
2。ハッシュコードの位置決めを使用して、配列subscriptを見つけて、リンクリストのリンクヘッダーを取得します。
3.リンクリストをトラバースして、同じキーがあるかどうかを確認します。判断の根拠はe.hash == hash &&((k = e.key)== key || key.equals(k))です。リリーを追加するとき、等しい方法が書き換えられるため、TOMを横断するときに2番目の条件が真であるはずです。しかし、ハッシュコードメソッドは引き続き親クラスを使用しているため、TomとLilyのハッシュコードは異なります。つまり、ハッシュコードは異なり、最初の条件は偽です。ここでは、2つのオブジェクトが異なるため、ハッシュセットはリリーをうまく追加します。
その理由は、ハッシュコード法が書き換えられていないからです。これが変更です:
パブリッククラステスト{public static void main(string [] args){desute stu = new Student(123、 "tom"); hashset <sudent> set = new hashset <>(); set.add(stu); set.add(new sudine(456、 "jerry")); set.add(new desutor = set); iterator( "); iterator); while(iterator.hasnext()){desute sustent = iterator.next(); System.out.println(desutent.getStunum() + "---" + sustent.getName());}}} name;}@overridepublic boolean equals(object obj){if(this == obj)return true; if(obj instanceof student){if(this.getStunum((学生)obj).getSunum())return true;} return false;}@rurtion int inthcode()出力:
456 ---ジェリー
123 ---トム
ハッシュコードメソッドを書き直し、学生番号を返します。わかりました、それは完了です。
一部の人々は、e.hash == hash &&((k = e.key)== key || key.equals(k))が少し複雑ですか? Equalsメソッドを使用するだけで十分だと思います。ハッシュコードを一度に判断する必要があるのはなぜですか?
ハッシュマップのリンクリスト構造で移動して判断する場合、書き換えられた等しい方法のビジネスロジックは、特定の状況でオブジェクトが等しいかどうかを比較するためにより複雑であり、ループダウンのビジネスロジックは検索効率に影響します。そこで、ここでは、ハッシュコードの判断を最初に置きます。ハッシュコードが等しくない限り、プレイが終了し、複雑な等しいと呼ぶ必要はありません。ハッシュマップの効率を大幅に向上させます。
したがって、ハッシュコード法は、ハッシュマップがハッシュコードと等しい比較の両方であるかどうかを決定するため、ハッシュマップなどのコレクションクラスを正常に使用できるようにすることです。この実装は、ハッシュマップの効率を改善することです。