ウィキペディアのハッシュコードについて:
Javaプログラミング言語では、すべてのクラスが暗黙的または明示的にHashCode()メソッドを提供します。これは、クラスのインスタンスで保存されているデータを単一のハッシュ値(32ビット署名整数)に消化します。
ハッシュコードは、オブジェクトインスタンスに保存されているすべてのデータに基づいて、32ビット整数を抽出します。この整数の目的は、インスタンスの独自性を示すことです。これはMD5コードに多少似ており、各ファイルはMD5アルゴリズムを介して一意のMD5コードを生成できます。ただし、Javaのハッシュコードは、各オブジェクトの一意のハッシュコードを生成するためのハッシュコードを実際に実装せず、まだ複製の可能性があります。
最初にオブジェクトクラスを見てみましょう。オブジェクトクラスは、Javaプログラムのすべてのクラスの直接または間接の親クラスであり、クラスレベルの最高点にあることを知っています。次のように、私たちが話したいハッシュコード法を含む、多くの一般的な方法がオブジェクトクラスで定義されています
パブリックファイナルネイティブクラス<?> getClass(); public Native int hashcode(); public boolean equals(object obj){return(this == obj); } public string toString(){return getClass()。getName() + "@" + integer.tohexstring(hashcode()); }ハッシュコード法の前にネイティブ修飾子があることに注意してください。つまり、ハッシュコード法は非ジャバ言語で実装されています。特定の方法は外部から実装され、メモリオブジェクトのアドレスを返します。
多くのJavaクラスでは、等しいとハッシュコードメソッドが書き換えられます。なぜこれがなぜですか?同じ文字を持つ2つの文字列を定義する場合など、最も一般的な文字列クラスは、それらを比較するときに、必要な結果は等しくなければなりません。 2つのオブジェクトのメモリアドレスが異なるため、等しいコードメソッドとハッシュコードメソッドをオーバーライドしないと、それらは間違いなく等しくありません。
public int hashcode(){int h = hash; if(h == 0){int off = offset; char val [] = value; int len = count; for(int i = 0; i <len; i ++){h = 31*h+val [off ++]; } hash = h; } return h; }実際、このコードはこの数学的表現の実装です
s [0]*31^(n-1) + s [1]*31^(n-2) +… + s [n-1]
s [i]は文字列のi番目の文字であり、nは文字列の長さです。では、なぜ他の数字ではなくここで31を使用するのですか?効果的なJavaはこれを言っています:31が選ばれた理由は、それが奇妙な素数であるためです。乗数が偶数であり、乗算がオーバーフローしている場合、2の乗算はシフト操作に相当するため、情報は失われます。素数を使用することの利点は明らかではありませんが、ハッシュの結果は、ハッシュの結果を計算するために従来使用されています。 31には優れた機能があります。これは、乗算の代わりにシフトと減算を使用して、より良いパフォーマンスを得ることです。31*i ==(i << 5)-i。 VMはこの最適化を自動的に完了できます。
ご覧のとおり、文字列クラスはその値値をパラメーターとして使用してハッシュコードを計算します。つまり、同じ値が間違いなく同じハッシュコード値を持つことになります。値も同じであるため、これは簡単に理解できます。したがって、等しい比較も等しい場合、等しい方法は等しい場合、ハッシュコードは等しくなければなりません。逆の方法は必ずしも真実ではありません。同じハッシュコードに同じオブジェクトが必要であることが保証されません。
優れたハッシュ関数は次のようになります。異なるオブジェクトに対して不均等なハッシュコードを生成します。
理想的な場合、ハッシュ関数は、セット内の不均等なインスタンスをすべての可能なハッシュコードに均等に分布させる必要があります。この理想的な状況を達成することは非常に困難です。少なくともJavaはそれを達成していません。ハッシュコードが非ランダムに生成され、特定のルールがあり、上記の数学的方程式であることがわかるためです。たとえば、同じハッシュコードを持っているが、異なる値値を持つものを構築できます:AAとBBのハッシュコードは同じです。
次のコード:
public class main {public static void main(string [] args){main m = new main(); System.out.println(m); system.out.println(integer.tohexstring(m.hashcode()));文字列a = "aa";文字列b = "bb"; system.out.println(a.hashcode()); system.out.println(b.hashcode()); }}出力結果:
Main@2A139A55 2A139A55 2112 2112
一般に、等しい関数を書き換えるときは、ハッシュコード関数を書き換える必要もあります。なぜこれがなぜですか?
この例を見てみましょう、シンプルなクラスの従業員を作成しましょう
Public Class Employee {private Integer ID;プライベート文字列firstName;プライベート文字列lastName;プライベートストリング部門。 public Integer getId(){return id; } public void setid(integer id){this.id = id; } public string getFirstName(){return firstName; } public void setFirstName(string firstName){this.firstname = firstName; } public string getLastName(){return lastName; } public void setLastName(string lastname){this.lastname = lastname; } public string getDepartment(){return Department; } public void setDepartment(String Department){this.department = department; }}上記の従業員クラスには、非常に基本的なプロパティとゲッターとセッターのみがあります。ここで、2人の従業員を比較する必要がある状況を検討してください。
public class equalstest {public static void main(string [] args){employee e1 = new Employee();従業員e2 = new Employee(); E1.SetID(100); E2.SetID(100); //コンソールsystem.out.println(e1.equals(e2))にfalseを印刷します。 }}上記のプログラムがfalseを出力することは間違いありませんが、実際、上記の2つのオブジェクトは従業員を介して表されます。本当のビジネスロジックは、私たちが真実を返すことを望んでいます。
これを達成するには、Equalsメソッドを書き直す必要があります。
public boolean equals(object o){if(o == null){return false; } if(o == this){return true; } if(getClass()!= o.getClass()){return false; }従業員e =(従業員)o; return(this.getid()== e.getid();}この方法を上記のクラスに追加すると、euqlStestが真に出力されます。
それで私たちは終わりましたか?いいえ、テスト方法を変更して見てみましょう。
java.util.hashset; Import java.util.set; public class equalttest {public static void main(string [] args){従業員e1 = new Employee(); e1.setid(100); e2.setid(100); hashset <employee>(); employes.add(e1); employes.add(e2); // 2つのobjectssystem.out.println(従業員);}を印刷する上記のプログラムは2つの結果を出力します。 2つの従業員オブジェクトがtrueを返す場合、セットに1つのオブジェクトのみを保存する必要があります。何が問題ですか?
2番目の重要な方法HashCode()を忘れました。 JDKのJavadocが言ったように、equals()メソッドを書き換えた場合、HashCode()メソッドを書き換える必要があります。次の方法を追加しましょう。プログラムは正しく実行されます。
@override public int hashcode(){final int prime = 31; int result = 1; result = prime * result + getId();返品結果; }覚えておくべきこと
オブジェクトの同じプロパティを使用して、HashCode()とequals()の2つの方法を生成することを確認してください。私たちの場合、従業員IDを使用します。
eqAulsメソッドは一貫している必要があります(オブジェクトが変更されていない場合、等しい値は同じ値を返す必要があります)
a.equals(b)、a.hashcode()がb.hashcode()に等しくなければならない限り、いつでも。
どちらも同時に書き直さなければなりません。
要約します
上記は、Javaのハッシュコード法に関するこの記事の詳細な理解に関するものであり、すべての人に役立つことを願っています。興味のある友人は、このサイトの他の関連トピックを引き続き参照できます。欠点がある場合は、それを指摘するためにメッセージを残してください。このサイトへのご支援をありがとうございました!