6

1000個のオブジェクトをハッシュセットに格納する必要があると仮定します。各オブジェクトを含む1000個のバケット(各オブジェクトのハッシュコードに一意の値を生成することにより)、またはおよそ100個のオブジェクトを含む10個のバケットがある方がよいでしょうか。

一意のバケットを持つことの1つの利点は、equals()メソッドを呼び出す際の実行サイクルを節約できることです。

バケットの数を設定し、それらの間にオブジェクトをできるだけ均等に分散させることが重要なのはなぜですか?

バケットに対するオブジェクトの理想的な比率は何でしょうか?

4

3 に答える 3

8

バケットの数を設定し、それらの間にオブジェクトをできるだけ均等に分散させることが重要なのはなぜですか?

AHashSetは、平均してO(1)時間のメンバーシップを判別できる必要があります。ドキュメントから:

このクラスは、ハッシュ関数が要素をバケット間で適切に分散することを前提として、基本操作(追加、削除、包含、およびサイズ設定)に対して一定時間のパフォーマンスを提供します。

これを実現するためにaが使用するアルゴリズムはHashset、オブジェクトのハッシュコードを取得し、これを使用して正しいバケットを見つけることです。次に、等しいアイテムが見つかるまで、バケット内のすべてのアイテムを繰り返し処理します。バケット内のアイテムの数がO(1)より大きい場合、ルックアップにはO(1)時間より長くかかります。

最悪の場合(すべてのアイテムが同じバケットにハッシュされる場合)、オブジェクトがセットに含まれているかどうかを判断するのにO(n)時間がかかります。

バケットに対するオブジェクトの理想的な比率は何でしょうか?

ここには時空のトレードオフがあります。バケットの数を増やすと、衝突の可能性が低くなります。ただし、メモリ要件も増加します。ハッシュセットには2つのパラメーターがinitialCapacityあり、作成するloadFactorバケットの数を調整できHashSetます。デフォルトの負荷率は0.75で、これはほとんどの目的で問題ありませんが、特別な要件がある場合は、別の値を選択できます。

これらのパラメータの詳細については、次のドキュメントを参照してHashMapください。

この実装は、ハッシュ関数が要素をバケット間で適切に分散させることを前提として、基本操作(getおよびput)に一定時間のパフォーマンスを提供します。コレクションビューの反復には、HashMapインスタンスの「容量」(バケットの数)とそのサイズ(キーと値のマッピングの数)に比例する時間が必要です。したがって、反復パフォーマンスが重要な場合は、初期容量を高く設定しすぎない(または負荷率を低く設定しすぎない)ことが非常に重要です。

HashMapのインスタンスには、そのパフォーマンスに影響を与える2つのパラメーターがあります。初期容量と負荷率です。容量はハッシュテーブル内のバケットの数であり、初期容量は単にハッシュテーブルが作成されたときの容量です。負荷率は、容量が自動的に増加する前にハッシュテーブルがどれだけいっぱいになるかを示す尺度です。ハッシュテーブルのエントリ数が負荷率と現在の容量の積を超える場合、rehashメソッドを呼び出すことで容量が約2倍になります。

原則として、デフォルトの負荷率(.75)は、時間とスペースのコストの間の適切なトレードオフを提供します。値を大きくすると、スペースオーバーヘッドは減少しますが、ルックアップコストが増加します(getおよびputを含むHashMapクラスのほとんどの操作に反映されます)。再ハッシュ操作の数を最小限に抑えるために、初期容量を設定するときに、マップ内の予想されるエントリ数とその負荷率を考慮する必要があります。初期容量が最大エントリ数を負荷率で割った値よりも大きい場合、再ハッシュ操作は発生しません。

于 2012-07-13T10:26:03.983 に答える
1

要素ごとにおよそ1つのバケットがプロセッサに適していますが、バケットが多すぎるとメモリに悪影響を及ぼします。Javaは少量のバケットから開始し、HashSetがいっぱいになり始めると自動的に容量を増やすため、アプリケーションのパフォーマンスに問題があり、原因としてハッシュセットを特定しない限り、実際に気にする必要はありません。

各バケットに複数の要素がある場合、ルックアップに時間がかかり始めます。空のバケットがたくさんある場合は、必要以上のメモリを使用しているため、要素の反復処理に時間がかかります。

ただし、これは時期尚早の最適化が行われるのを待っているようです。ほとんどの場合、デフォルトのコンストラクターで問題ありません。

于 2012-07-13T10:28:43.730 に答える
1

Object.hashCode()タイプは2^32intの異なる値しか持てないため、バケットを作成してオブジェクトをそれらの間に分散します。

編集:バケットを使用し2^32て2 ^ 32オブジェクトを格納している場合、反抗的にget操作を行うと一定の複雑さが得られますが、オブジェクトを格納するために要素を1つずつ挿入している場合、バケットとして2^32使用している場合よりもObject[]毎回再ハッシュが実行されますその長さを超えると、より大きなサイズarrayの新しい配列が作成され、要素がこれにコピーされます。このプロセスは複雑さを増します。だからこそ、私たちは比率を利用し、それはより良いものを提供することによってそれ自体で行われます。equalshashcodeHashsetshashing algorithm

于 2012-07-13T10:29:13.620 に答える