ハッシュコードの理解

ハッシュ

ハッシュとは何ですか

ハッシュ、またはハッシュハッシュ翻訳、(また、プレマッピングと呼ばれる)任意の長さの入力であり、ハッシュアルゴリズム、固定長の出力を得るために、出力はハッシュ値です。この変換は、圧縮マップ、空間ハッシュ値は、典型的には、入力空間よりもはるかに小さい、そのようなものとして、異なる入力が同一のハッシュ値を取得することができるです。ハッシュ値が一意の入力値により決定することができません。帳に任意の長さの単純なメッセージは、固定長メッセージダイジェスト関数に圧縮されます。

機能

同じハッシュ値は、必ずしも同一の目的は、異なるオブジェクトのハッシュ値が同じであってもよいです。
長さは、彼よりも短いマッピングされているため、固定長の任意の長さのマッピングは、ハッシュの衝突は発生し得ます。

共通のハッシュ関数

直接アクセスConormal

全体の法律への乗数

平方取中法

ハッシュコード

整数値を得るためにハッシュテーブル内の代表的な位置、またはハッシュ関数の性質は、ハッシュ値のペアであるとしてハッシュコードハッシュは、によって得られます。(異なるアルゴリズムの異なる画像をハッシュコード)。
が、ハッシュコードは、ハッシュテーブル内の位置を表すが、この位置は、ハッシュ関数ではなく、ハッシュのルックアップテーブルの取得によって得られます。
簡潔には、ハッシュ・テーブル内の位置であり、位置は、アルゴリズムによって得られた物体のハッシュコードによって示されます。
ない方法は、ハッシュコードを取得しないようにするので、なぜ、基本データ型には、このHashMapを使用しない理由です。

Object.hashCode()

画像のハッシュコードメソッド呼び出しは、ネイティブメソッドであり、これは、整数値が得られたハッシュ関数のリターンを計算することにより、画像は整数であろう場所の物理アドレスに変換しました。2つのオブジェクトが同じに等しい場合は、ハッシュコードは、我々は、オブジェクトを定義する際に、通常のequalsとhashCodeの原因を書き換える理由である、同じでなければなりません。

イコールとハッシュコード:
あなたがオーバーライドしない場合は、すべての新しいオブジェクトが同じ(異なるイコールではありません、等しいデフォルトの比較は、オブジェクトへの2つの参照のアドレスであるそうであることを確認、が、我々は値が等しくすることができると信じて、一般的にあるため、 )それはequalsメソッドをオーバーライドします、とhashCodeとequalsが関連しているので、ので、hashCodeメソッドをオーバーライドします。
2つのオブジェクトが必ずしも同じ同じ、その後、ハッシュコードに等しい場合。
異なるハッシュコードの二つの物体場合は、等号は異なっている必要があります。

Objects.hashCode()、をArrays.hashCode()

 public static int hash(Object... values) {
        return Arrays.hashCode(values);
    }

//这个是Array.hashCode()    
public static int hashCode(Object a[]) {
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a)
            result = 31 * result + (element == null ? 0 : element.hashCode());

        return result;
    }

Objects.hashCodeは、パラメータオブジェクトの配列を変換することによって、オブジェクトの種類に応じて適切なハッシュコードを呼び出し、ハッシュコードオブジェクトを運んで、計算されます。

String.hashCode()

    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

文字列に文字列、H = 31 * H +ヴァル[i]は、ハッシュASCII文字コードによって計算され、31が配置されている理由は、後述します。

Interger.hashCode()

  public static int hashCode(int value) {
        return value;
    }

直接の戻り値

ハッシュコードの役割

ハッシュコードが計算され、オブジェクトの位置は、標的化の効率を改善するために、ハッシュテーブルをトラバースすることによって場所を見つける必要とせずに、直接ハッシュテーブルに対応し得ることができます。
たとえば、次の場合店私たちは、あなたが預金が前の900を比較する必要があるとき900、901のために保存されている、とhashCodeにより非常に多くの時間を比較していない場合、1000の数を持っています。それは唯一のコーエンのハッシュの競合です。しかし、効率は依然として高いです。

イコール和のhashCode

なぜ一般的にオーバーライドは書き換えhahsCodeが等しくなければならない
あなたが等号をオーバーライドする場合は、ハッシュコードは、理論的には、彼らが同じ位相を行う必要があり、その後、等号と同時に二つのオブジェクト、その後、ハッシュコードを書いていないが、実際に、それは違うと思います。だから、書き直すことにします。
デフォルトでは、オブジェクトのアドレスへの2つの等号の参照を比較することで必ずそう、が、一般的に、我々は値が等しくすることができると考えているため、ハッシュコードとequalsが関連しているので、彼らはハッシュコードを上書きしますので、それらは、equalsメソッドをオーバーライドし、う方法。

		TestMe me = new TestMe("nan");
        TestMe metwo = new TestMe("nan");
        TestMe mePointer = me;
        System.out.println(me.hashCode());
        System.out.println(mePointer.hashCode());
        System.out.println(metwo.hashCode());
        System.out.println(mePointer.equals(me));
        //输出
        //1956725890
        //1956725890
		//356573597
		//true

なぜ31であります

彼は奇素数であるので、31を使用する理由。乗数が偶数、次いでオーバーフロー乗算である場合、シフト動作は2(低補0)を乗算と等価であるため、データが失われることになります。

  • 素数を使用する理由は、素数を乗じて、それが競合しにくいです。それ自体の唯一の素因数ので。
    7,8:例えば
    算出"4 2"、ハッシュコード7 = 2 + 4 = 18であり、他の8 ; 2 + 4 = 20
    "12が1"計算する際に、ハッシュコード= 7 。1. 19 = + 12です。別の8 1 + 12 = 20、コンフリクト。

  • 理由31が決定によって配布され、より大きな、より大きなオーバーフローの可能性が、衝突の小さい、可能性。

  • 31は、良好な性能を持っている、すなわち、代わりに乗算と減算のシフトは、より優れた性能を得ることができる:31 * iが==(私は<< 5) - I、 VM近代的なこの最適化を自動的に行うことができます。この式は非常に単純な推論することができます。

  • このことは、(32できI <<。5 = Iは、次いで、31であるような63のように、IはI-I <<。= 5)がそうであってもよいです

  • 最も重要なことは、パフォーマンスで使用するためには31。もちろん、あなたも63を使用することができます。しかし、63オーバーフローリスクはさらに大きくなります。それが15だから、?また、利用可能だと思います。(より大きい、コンフリクトのための潜在的に小さいが、スペースをオーバーフローさせ、大きくてもよく、小さく、衝突の可能性は、少ない流出)。

公開された12元の記事 ウォンの賞賛0 ビュー189

おすすめ

転載: blog.csdn.net/N_a_n/article/details/105192791