2017-08-02 1 views
1

のJava HashMapのソースコードを通過する間に、我々はキーの最初のバケットは以下のような方法で決定されて見ることができます。私の理解あたりとして容量とJavaのHashMapでindexFor

static int indexFor(int h, int length) { //h = hash of key 
    return h & (length-1);    //length = capacity of array at 
}          //   current time 

初期サイズであれば16(length-1 = 15 = 1111)であり、キー​​の生成ハッシュが108378(1 10100111 01011010)の場合、 indexFor()メソッドは10(1010)を返します。

今や、いくつかの追加の後、容量が32に変更されました。ここでキー​​(ハッシュ108378)を検索する場合は、同じindexFor()メソッドのバケットを再度チェックします。 h & (length-1)コードスニペットは26を返します。 (108378 & 31)。

私の質問は、テーブルがサイズ変更された場合、メソッドが正しいバケットを見つける方法ですか?

+1

テーブルのサイズを変更すると、バケットが再構成されます。 – shmosel

+0

テーブルのサイズを変更すると、キーのすべてのハッシュ値が再計算され、移動されます。 – 4castle

答えて

1

負荷係数の最大しきい値に達すると、Rehashingと呼ばれるプロセスが発生し、すべての要素が新しいテーブルに移動します。ハッシュテーブルのエントリ数が 負荷係数と現在の容量の積を超える

、ハッシュテーブルは が再ハッシュされ(すなわち、内部データ構造が再構築されている)ので ことハッシュテーブルのバケット数は約2倍です。

マップの予想されるエントリ数とその負荷係数 は、初期容量を設定するときに考慮する必要があります。したがって、再ハッシュ操作の回数を最小限に抑えるために です。

+0

ありがとうございます。あなたの答えの延長線上に私は別の質問があります。再結合中に連鎖がすでに適用されている場合は、連鎖ノードのバケット番号も再計算されますか?または、チェーンされたノードの開始ノードだけですか? –

+0

以前の同じバケット位置を保持するノードは、異なるバケット位置に分散することができるため、すべての値に対して再計算が行われます。 –

1

テーブルのサイズが変更されると、lengthパラメータが変更され、indexForメソッドは異なる値を返します。テーブルのサイズが変更されると、現在テーブルにある値を新しいテーブルに移動する必要があります。したがって、新しいインデックスが各値に対して計算されます。

+0

さて、私はそれを得ました。ありがとう。しかし、私が驚いたのは、サイズを変更するときの時間と空間の複雑さです。それは操作中にO(n)の複雑さに従うものではありません。 –

+0

@AnirbanB再ハッシュ中には、古いハッシュテーブルにあったすべての要素が計算された新しいハッシュコードを持っていなければならないので、時間の複雑さはO(n)であるため、計算されたインデックスは新しいテーブルに配置されます。 1つの要素を追加するだけでは効率的ではありませんが、まだO(n)です。 –

+0

ええと...ちょうどそれが実際にはO(n)であることが分かりました。しかし、平均ケースシナリオはO(1)です。しかし、空間の複雑さはO(n)よりはるかに大きい。 –

0

表示されているlengthは、map.size()によって報告された値ではありません。これは、ハッシュテーブルのサイズを表す内部長です。この長さは、密度の高いハッシュマップではsize()より小さくなることがあります。まばらに埋め込まれたハッシュマップでは、size()よりも大きくなることがあります。値が小さいほど、h & (length-1)の評価が同じキーが見つかるほど、より多くのキーがバケットにグループ化されます。いくつかの(できるだけ願わくは等の希)時点

時間にマップは、あまりにも多くの衝突、(各バケットにあまりにも多くのキーを)引き起こし、lengthが小さすぎると判断したのでハッシュを再割り当て、マップを再編成すべてのハッシュ値を再計算し、バケットでキーを再配布して、h & (length-1)がすべてのハッシュ値に対して正しいことを確認してください。

関連する問題