Java hashCode() メソッドの深い理解

黄舟
リリース: 2017-04-01 10:45:24
オリジナル
1496 人が閲覧しました

Java.lang.ObjectにはhashCode()メソッドとequals()メソッドがあり、これら2つのメソッドはソフトウェア設計において極めて重要な役割を果たします。一部のクラスでこれら 2 つのメソッドをオーバーライドして、いくつかの重要な機能を完了します。この記事では、hashCode() が使用される理由、その使用方法、およびその他の拡張機能について説明します。この記事を読むには、ハッシュ アルゴリズムの基本的な知識と Java コレクションの基本的な知識が必要です。この記事は初心者向けの入門レベルの説明です。時間を無駄にしないように、読んだ後に右上隅の [X] をクリックしてください。 _^。

WHY hashCode()?

setSet 内の要素は順序付けされておらず、反復可能ではありません。では、2 つの要素が繰り返されるかどうかを判断する根拠は何でしょうか。 「オブジェクト が等しいかどうかを比較するには、もちろん Object.equal() を使用します。」と、ある猿が言いました。しかし、Set 内のオブジェクトの数が多く、後から Set に追加されたオブジェクト要素の比較回数が徐々に増加し、プログラムの実行効率が大幅に低下します。 Java では、この問題を解決するためにハッシュ アルゴリズム (ハッシュ アルゴリズムとも呼ばれます) を使用し、オブジェクト (またはデータ) を特定のアルゴリズムに従ってアドレスに直接マッピングし、オブジェクトへのアクセス効率を大幅に向上させます。このように、多数の要素を含むセット Set に要素 (オブジェクト) を追加する必要がある場合、最初にこの要素の hashCode() を呼び出すと、この要素の実際の格納場所が存在しない場合にすぐに見つけることができます。この位置にオブジェクトがある場合は、このオブジェクトがコレクション Set に初めて格納されるときに、この位置にオブジェクトが直接格納されます。この位置にオブジェクトがある場合は、equal() を呼び出して、この 2 つが一致するかどうかを確認します。オブジェクトが等しい場合、要素は破棄され、等しくない場合、要素は他のアドレスに格納されません。

hashCode() の使用方法?

Java 言語には、equal() を設計するときに従う必要がある 5 つの要件があります。

  1. 対称性。 a.equal(b) が "true" を返す場合、b.equal(a) も "true" を返す必要があります。

  2. 反射率。 a.equal(a) は "true" を返さなければなりません。

  3. 推移性。 a.equal(b) が "true" を返し、b.equal(c) が "true" を返す場合、c.equal(a) は "true" を返す必要があります。 a.equal(b) が "true" を返す場合、a と b の内容が変わらない限り、a.equal(b) は何度繰り返しても "true" を返さなければなりません

  4. 。 a.equals(null) の場合、常に "false" を返します。 a.equals (a とは異なる型のオブジェクト) は常に "false" を返します。 hashCode() と equals() の戻り値の関係。

  5. a.equals(b) が「true」を返す場合、a と b の hashCode() は等しい必要があります。
  6. a.equals(b) が "false" を返す場合、a と b の hashCode() は等しいか、異なる可能性があります。

    これが例です。実際のソフトウェア開発では、この 2 つのメソッドを書き換えるのが最善です。
  1. public class Employee {
        int        employeeId;
        String     name;
    
        // other methods would be in here 
    
        @Override
        public boolean equals(Object obj)
        {
            if(obj==this)
                return true;
            Employee emp=(Employee)obj;
            if(employeeId.equals(emp.getEmployeeId()) && name==emp.getName())
                return true;
            return false;
        }
    
        @Override
        public int hashCode() {
            int hash = 1;
            hash = hash * 17 + employeeId;
            hash = hash * 31 + name.hashCode();
            return hash;
        }
    }
    ログイン後にコピー

    以下では、一般的に使用されるクラスの hashCode() 実装メソッドに焦点を当てます。 Stringクラスの

  2. hasCode()
  3. Javaコード

    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;
        }
    ログイン後にコピー
  4. このコードで最も興味深いのは、ハッシュの実装方法です。最終的に計算されたハッシュ値は次のとおりです:

s[0]31

n-1

+ s[1]31

n-2

+ … + s[n-1]

s[i] は文字列ですi 番目の文字、n は文字列の長さです。では、なぜここでは

他の
数値の代わりに 31 が使用されているのでしょうか?

31 は奇数の素数であり、乗数が偶数で乗算がオーバーフローした場合、2 の乗算はビット シフトに相当するため、情報が失われます。操作 。素数を使用する利点はすぐには明らかではありませんが、ハッシュ結果の計算には素数を使用するのが一般的です。 31 には、乗算の代わりにシフトと減算を使用する優れた機能があり、これによりパフォーマンスが向上します: 31*i==(i<<5)-i。現在の VM は、この最適化を自動的に 完了できます。 (Effective Javaより) オブジェクトクラスの

オブジェクトクラスhasCode()

hashCode()はNativeメソッドです。 Nativeメソッドの呼び出し方

public native int hashCode();
ログイン後にコピー
ObjectクラスのNativeメソッドクラスはこちらです。 詳細な分析については、別のブログをお読みください
static JNINativeMethod methods[] = {
    {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
    {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
    {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
    {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
    {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
};
ログイン後にコピー
ソースコードには getClass() (58 行目参照) などが含まれています。 hashCode() (43 行目参照) は JVM_IHashCode へのポインタとして定義されています。 jvm.cpp は、JVM_IHashCode(行 504)

関数 を定義します。この関数は、synchronizer.cpp にある ObjectSynchronizer::FastHashCode を呼び出します。行 576 の FastHashCode と行 530 の get_next_hash を参照してください。

以上がJava hashCode() メソッドの深い理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!