転送:プログラマー小さな灰色(マイクロ・シグナル:chengxuyuanxiaohui)
------------
我々はすべて知っているように、HashMapのキーと値のストアキーと値のペアの収集、また、エントリと呼ばれる各キーと値のペアです。これらのキーと値のペアの配列に格納されている(エントリ)分散体は、アレイは、ハッシュマップのバックボーンです。
アレイハッシュマップの各要素の初期値はNULLです。
getおよびput:HashMapのために、我々は、最も一般的に用いられる2つの方法があります。
原則1、置く方法
どのようなことが起こったとき、Putメソッドを呼び出すには?
例えば、hashMap.put(「りんご」、0)を呼び出し 、 「りんご」の要素のキーを挿入します。:今回はエントリの挿入位置(インデックス)を決定するためにハッシュ関数を使用する必要が
指数=ハッシュ(「アップル」)
次のように最後に、インデックスは2により算出されることを前提とし、結果は以下の通りでした。
HashMapのの長さが限られているのでしかし、挿入されたエントリが上昇すると、その後、完璧なハッシュ関数は、必然的に状況インデックスの競合が発生します。たとえば、次のよう:
この時間は、どのようにそれを行うには?我々は解決するために、リストを使用することができます。
配列の各要素は、ハッシュマップエントリオブジェクト以上で、リストの先頭はノードです。次のオブジェクトへの各エントリポイントは、ポインタエントリ次ノードです。アレイの新たな位置がエントリの競合にマッピングされる場合、それだけでは、対応するリンクに挿入する必要があります。
なお、使用してリンクリストに新しいエントリノード、「頭補間を。」リストの末尾を挿入していない理由については、後ほどについて説明します。
2、Getメソッドの原則
その後、何が起こったのか時間を、見つけるために、キー値に応じてgetメソッドを使用しますか?
まず、ハッシュキーマッピングを行います入力は、対応するインデックスを与えるために:
インデックス=ハッシュ(「アップル」)
由于刚才所说的Hash冲突,同一个位置有可能匹配到多个Entry,这时候就需要顺着对应链表的头节点,一个一个向下来查找。假设我们要查找的Key是“apple”:
第一步,我们查看的是头节点Entry6,Entry6的Key是banana,显然不是我们要找的结果。
第二步,我们查看的是Next节点Entry1,Entry1的Key是apple,正是我们要找的结果。
之所以把Entry6放在头节点,是因为HashMap的发明者认为,后插入的Entry被查找的可能性更大。
3、HashMap的初始长度
之前说过,从Key映射到HashMap数组的对应位置,会用到一个Hash函数:
index = Hash(“apple”)
如何实现一个尽量均匀分布的Hash函数呢?我们通过利用Key的HashCode值来做某种运算。
index = HashCode(Key) % Length ?
如何进行位运算呢?有如下的公式(Length是HashMap的长度):
index = HashCode(Key) & (Length - 1)
下面我们以值为“book”的Key来演示整个过程:
1.计算book的hashcode,结果为十进制的3029737,二进制的101110001110101110 1001。
2.假定HashMap长度是默认的16,计算Length-1的结果为十进制的15,二进制的1111。
3.把以上两个结果做与运算,101110001110101110 1001 & 1111 = 1001,十进制是9,所以 index=9。
可以说,Hash算法最终得到的index结果,完全取决于Key的Hashcode值的最后几位。
假设HashMap的长度是10,重复刚才的运算步骤:
单独看这个结果,表面上并没有问题。我们再来尝试一个新的HashCode 101110001110101110 1011:
私たちは別のハッシュコード101110001110101110 1111を検索してみましょう:
はい、0から第1への第二逆数ハッシュコードは、演算の結果1001です。つまり、ときHashMapの長さ10の、時にいくつかの指標結果のオッズが大きくなり、そしていくつかの指標の結果は、(0111など)が発生したことがありません!
これは明らかに均等に分散ハッシュアルゴリズムの原理と矛盾しています。
一方、16の長さ又は2のパワー、長-1の値が全てのビットがこの場合には、全て1であることであり、結果は数ビットのハッシュコードの値の指標に相当します。ハッシュコード自体があれば、入力分布として、結果のハッシュアルゴリズムが均一です。