HashMapの(JDK1.7)の原則の最も詳細な分析(A)

いいえ公共:大サブ速歩プログラマません

JDK1.7では、ハッシュマップの+は、配列リストによって達成され、以下のように、原理は次のとおり

HashMap map = new HashMap(); // 伪初始化
map.put("键""值"); // 真初始化
复制代码


実行HashMapの設定方法は、サイズ0の配列テーブルを初期化します。
最初の実行のHashMapのPUT方法が真となり、0に初期化されている場合、テーブルのサイズも遅延初期化と呼ばれる、0であるか否かを判定する。
真の初期化は、配列のデフォルトのサイズは16である場合には、もちろん、あなたがHashMapを呼び出すことができますによって、アレイの容量を初期化するコンストラクタを指定するパラメータを持っていますが、あなたが本当に最終決定権を持っているもの、例えば、あなたが今の配列を望んでいないことに注意してください、6の初期容量は、次にハッシュマップは、サイズ8の配列を生成し、あなたは20のアレイ初期容量にしたい場合は、ハッシュマップを使用して、配列のサイズnを初期化するサイズ32の配列、すなわち、生成しますしかし、ハッシュマップのサイズに初期化数よりも多いNの二乗に等しいアレイ。それは理由として、我々は対処う。

テーブルが初期化されるか、またはその主要なタスクにわたって初期化されている必要はないPUT方法については、次のキー値であり、配列またはリストに格納されています。それでは、どのように配列に堆積させるためのキー値は行くのだろうか?
パラメータは配列のインデックスとして、それを送信する必要がないので、インデックスがどのようにハッシュマップであるときに我々はPUTを行いながら、我々は、我々はデータ配列に行きたい場合は、我々は最初の配列インデックスを持たなければならないことを知っていますそれを取得しますか?答えは、名前がハッシュマップその他のMAPと呼ばれていない理由であるハッシュアルゴリズム、です。

ハッシュアルゴリズムのために、それは一つの引数はハッシュコードを返し取るハッシュ関数を取ることを知っている必要があり、人々を知るために、ハッシュ関数の特性は、ハッシュコードのリターンのために同じ引数でなければなりません異なるために同じです引数は、関数が同じハッシュコードを返さないことがあり、同じパラメータにハッシュ関数のため、ご理解のポイントのように、同じハッシュコードにできるだけ多くを返さない、この衝突はハッシュまたはハッシュの競合と呼ばれています。

その後、我々は、配列のインデックスとして、このハッシュコードに直接来ることができ、別の非常に重要な問題です最後に、我々はする必要がありますキーハッシュまたは作るために値をハッシュを作るために、またはのためのキー値が同時にハッシュを作りますか?

GETは、唯一の引数としてキーを渡す必要があるが、実際には論理GETメソッドはすぐに配列インデックスはすぐにキーを見つけるために取得するためにキーハッシュ経由なのでまあ、今回は、考慮にGETメソッドがかかります対応する値。PUTメソッドのためので、2つのパラメータを渡されたが、すぐに見つけるために、GETメソッドを容易にするためにのみ、キーハッシュの配列のインデックスを取得することができますが。

しかし、問題があると、アレイはそれを添字としてそれを直接のhashCode?
ハッシュコードは、たとえば、通常、比較的多数です:

System.out.println("键".hashCode()); // 38190
// 为什么是这个结果,大家自行去看String类中的hashCode方法
复制代码

だから我々は、デジタル配列の添字ほど、どのように行うために置くことができませんか?
これは通常、剰余演算を考えるかもしれないが、剰余HashMapを使用しませんでしたが、:

static int indexFor(int h, int length) {
	// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
	return h & (length-1);
}
复制代码

このメソッドは、配列の下で、主題の方法である(JDK1.7HashMapをPUTとGETの2つの方法はPUTと取得する方法は添字を取得するために行かなければならないのですか?あなたはここを参照してください場合は、[はい、理解していない、あなたが考えるように行きます)それの処理ロジックの効率を向上させる上に言えばGETは、この方法Hはハッシュコード、配列の長さの長さの代表を表します。我々は、それが中で使用されることがわかった論理その後、問題が来て、操作、および論理演算を正確に配列の添字を計算することができますか?たのは計算させる、ハッシュコードは01010101(バイナリ表現)であると仮定すると、長さは、H&(長さ1)、次いで、00010000(バイナリ表現で16)です。

h:  0101 0101
15: 0000 1111
  &
    0000 0101
复制代码

我々の議論に業績の上記方法に関する値:高ニブル15は論理及び算術演算は2ビットであるが、下位4ビットは、1であり、0であるためには、1つのだけの結果が1であります、0000-1111:上記の計算の結果は確かに高いニブル0であり、下位4ビットとHの下位4ビットが同じであるので、範囲値hニブルの範囲の結果でありますそれは0-15であるので、この結果は、アレイの範囲の目標に沿ったものです。
だから、長さが17であることが想定されますか?SO 3 H・(長さ-1)でした。

h:  0101 0101
16: 0001 0000
  &
    0001 0000
复制代码

長さが17である場合、上記の動作の結果は良好ではないれ、いずれか2つだけの値のいずれか00000000、0001000の範囲です。

だから我々は我々の長さで、ハッシュコードのインデックス配列インデックス値の範囲をカバーするために変換したいならば、それはマイナス15(0000 1111)した後、それはこの長さが16であれば、非常に関連していることがわかりました0種が高い、2の低数は、我々が配列の添字をしたい取得した論理AND演算結果による任意のハッシュコードのためにそれを可能にするだけで作られています。HashMapの初期化にtrueの場合、配列の長さは、二次側の数、二次側と密接にグループに関連する演算インデックスの数、およびこのビットモジュロ演算がより高速であるなければならない理由です。

だから我々はこのについて推論することができます:PUTメソッドを呼び出すときに、キーハッシュは、ハッシュコードを取得した後、ロジックや操作によって配列のインデックスを取得渡され、最終的にこの配列の添字でキー値が存在しています。

メモリ位置がKEYVALUEことを決定した後、我々は、上述したように、異なるパラメータ、すなわちハッシュ衝突が発生し、ハッシュマップの反応である、PUTつの異なる鍵を得る可能性がある場合、同じハッシュコードを取得してもよいです同じ配列インデックスを取得するために、同じハッシュコードは、実際には、HashMapのと同じではありませんが、ハッシュコードに対応するキーは、それが論理AND演算した後、同じ配列インデックスを取得することも可能であったとしても、その後、時間のHashMapはそれに対処する方法ですか?はい、それはそれを達成するために、具体的方法を、リンクリストのですか?次の記事では、それを継続します。

私たちは経験を読んで、コードの塊を参照してくださいまた、小さな携帯電話の画面には好きではないので、私は、テキストのスタイルを書いていることは、通常のポイントより上になると考えています。

おすすめ

転載: juejin.im/post/5cf3a11851882566477b7a02