1.なぜhashcode()?
セットセットの要素は乱れており、抑制されていないので、2つの要素が繰り返されるかどうかを判断するための根拠は何ですか? 「もちろん、Object.equal()は、オブジェクトが等しいかどうかを比較するために使用されます」と特定の類人猿は言いました。ただし、セットには多数のオブジェクトがあり、セットに追加されたオブジェクト要素の比較数が徐々に増加し、プログラム操作の効率が大幅に低下します。 Javaは、ハッシュアルゴリズム(ハッシュアルゴリズムとも呼ばれます)を使用して、この問題を解決します。オブジェクト(またはデータ)は、特定のアルゴリズムに従ってアドレスに直接マッピングされ、オブジェクトのアクセス効率が大幅に改善されます。このようにして、要素(オブジェクト)を追加するために多数の要素を含むセットのセットが必要な場合、最初にこの要素のHashCode()を呼び出し、この要素の実際のストレージ位置を一度に配置できます。この位置に要素がない場合、オブジェクトがコレクションセットに初めて保存され、オブジェクトがこの位置に直接保存されることを意味します。この位置にオブジェクトがある場合は、Equal()を呼び出して、2つのオブジェクトが等しいかどうかを確認します。同じことが真の場合、要素を破棄し、存在しません。等しくない場合は、他のアドレスにハッシュします。
2. hashcode()をどのように使用しますか?
Java Languageには、APEデザインのEqual()に従う必要がある5つの要件があります。
対称。 A. Equal(b)が「True」を返す場合、B.Equal(a)も「true」を返す必要があります。
反射的。 A. equal(a)「true」を返す必要があります。
推移的。 A. equal(b)が「true」を返し、B. equal(c)が「true」を返す場合、C. equal(a)は「true」を返す必要があります。
一貫性。 A. Equal(b)が「True」を返す場合、AとBの内容が変わらない限り、A.Equal(b)は「true」を返す必要があります。
いずれにせよ、A.Equals(null)は常に「false」を返します。 A.エクアル(異なるタイプのオブジェクトとa)は常に「false」を返します。
HashCode()とequals()の返品値の関係。
a.equals(b)が「true」を返す場合、aとbのハッシュコード()は等しくなければなりません。
a.equals(b)が「false」を返す場合、aとbのハッシュコード()が等しいか、不平等である可能性があります。
これが例です。実際のソフトウェア開発では、これら2つの方法を書き直すことが最善です。
パブリッククラスの従業員{int EmployeeID;文字列名; //他の方法はここにあります@Override public boolean equals(object obj){if(obj == this)return true;従業員emp =(従業員)obj; if(employeed.equals(emp.getemployeeid())&& name == emp.getname())return true; falseを返します。 } @Override public int hashcode(){int hash = 1;ハッシュ=ハッシュ * 17 + EmployeeID; hash = hash * 31 + name.hashcode();ハッシュを返します。 }}3.以下は、一般的に使用されるクラスのハッシュコード()実装方法に焦点を当てています。
文字列クラスのhascode()
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] 31n-1 + s [1] 31n-2 +… + s [n-1]
s [i]は文字列のi番目の文字であり、nは文字列の長さです。では、なぜ他の数字ではなくここで31を使用するのですか?
31は奇妙な素数です。乗数が偶数であり、乗算がオーバーフローしている場合、2の乗算がシフト操作と同等であるため、情報は失われます。素数を使用することの利点は明らかではありませんが、ハッシュの結果は、ハッシュの結果を計算するために従来使用されています。 31には優れた機能があります。これは、乗算の代わりにシフトと減算を使用して、より良いパフォーマンスを得ることです。31*i ==(i << 5)-i。 VMはこの最適化を自動的に完了できます。 (効果的なJavaから)
オブジェクトクラスのhascode()
HashCode()は、オブジェクトクラスのネイティブメソッドです。ネイティブメソッドを呼び出す方法は?
public Native int hashcode();
オブジェクトクラスのネイティブメソッドクラスは、ここにあります。詳細な分析については、別のブログをお読みください
static jninativemethodメソッド[] = {{"hashcode"、 "()i"、(void *)&jvm_ihashcode}、{"wait"、 "(j)v"、(void *)&jvm_monitorwait}、{"notify"、 " "()v"、(void *)&jvm_monitornotifyall}、{"clone"、 "()ljava/lang/object;"、(void *)&jvm_clone}、};ソースコードには、getClass()(Line58)などが含まれます。HashCode()(Line43を参照)は、JVM_IHASHCODEのポインターとして定義されます。
jvm.cppは、jvm_ihashcode(行504)関数を定義します。この関数は、objectsynchronizer :: fasthashcodeを呼び出します。これは、Synchronizer.cppで決定されます。 576行目と530行目のget_next_hashでのfasthashcodeの実装については、576行目のfasthashcodeの実装と530行のget_next_hashを参照できます。