ハッシュマップ(無料アルゴリズムは、この部分の達成のために、この本を見てみることができ、それは理にかなっています)

//再現します。https://baijiahao.baidu.com/s ID = 1618550070727689060&WFR =クモ&= PCのため?

1、なぜHashMapの?

HashMapのキーと値のペア(キー値)マッピングに格納されている内容はハッシュバケット(アレイとリンクされたリスト)であり、リンクされたリストデータ構造のアレイを使用してハッシュマップおよび変更が容易とクエリの配列を線形探索を継承し、一覧表示することができ修飾アドレッシングHashMapのないので、すぐハッシュマップ、同期HashMapのヌルのキーと値が許容されるかもしれないが、ハッシュテーブル(HashMapの後にAPIを前処理することができるされているので理由であるequlas()メソッドは、オブジェクトを必要とする)ことができない2、HashMapを何が効きますか?

HashMapのは、ハッシュの原理に基づいて、我々は、get(キー)を使用してHashMapのにPUT(キー、値)ストレージオブジェクトを使用することはHashMapからオブジェクトを取得します。我々はput()メソッドへのキーと値を渡すとき、私たちは最初のhashCodeを計算して返すために、キーのhashCode()メソッドを呼び出してノードオブジェクトの配列を格納する場所の地図のバケツを見つけるために使用されます。キーポイントは、ここで注目され、HashMapのはMap.Nodeとして、バケットやオブジェクトの値にキーオブジェクトを格納することです。

以下ハッシュマップは、簡単なシミュレーションのデータ構造の初期化され、ノード[]テーブル=新しいノード[ 16] ハッシュ・バケット、テーブル初期化クラスをノード{ ハッシュの//値、ハッシュキー; //キー 値;の//値を 次のノード; //とリンクされたリストのいずれかを指す(ファスナー法と競合)}

以下は、特定のプット手順(JDK1.8版)されているキーハッシュ値を見つけるために、1、その後、添字を算出し、

2、直接バケツに衝突、(同じバケツに置く必要があることにより、計算と同じ意味衝突ハッシュ値)が存在しない場合

3、もし戻ってリンクする方法のリストに衝突

4、鎖長が閾値を超えた場合(TREEIFY閾値は== 8)、赤黒木リストターンに入れ、チェーン6の長さよりも短い、ブラックツリーリストを戻します

5、ノードがすでに存在する場合は、古い値を置き換えます

6、バケツがいっぱいになった場合(容量負荷率16 * 0.75)、あなたは(並び替え後の2倍の拡大を)サイズを変更する必要があります

ここでは(2つのキーが同じであれば、どのようにオブジェクトの値を取得するか、特別な事情のハッシュコードを検討?)プロセスを取得します、我々は(取得するために呼び出すときにキーオブジェクトのハッシュコードを使用する方法、HashMapのは、バケット位置を見つけるバケット位置を見つけ、呼ぶだろうが) keys.equals()メソッドを見てオブジェクトの最終的な値を見つけるために、リスト内の正しいノードを見つけます。

 

3.影響を軽減する方法はありますか?

 

摂動関数は、衝突を減らすことができ、原則的には、2つの等しくないオブジェクトが異なるハッシュコードを返した場合、その後、衝突の確率は、リスト構造を保つ意味し、小さくなることで低減され、その値が頻繁に等しいと呼ばれていませんこの方法、私たちはHashMapののパフォーマンスを向上させることができるように。(外乱すなわち、ハッシュ法アルゴリズム内の、異なるオブジェクトが異なるハッシュコードを返すようにする。)最終的な目的のために不変、宣言、及び適切な等号を(使用)とhashCode()メソッドは、衝突を減少させます発生。非変性バッファーのハッシュコードは文字列を使用して取得したオブジェクトの全体的な速度を改善する別のキーを、可能にする、そのようなキーとしてIntergerラッパークラスは非常に良い選択です。なぜ文字列、キーのIntergerなラッパークラス?文字列は最終であり、等号を書き換えた()とhashCode()メソッドを持っているので。hashCode()を計算するために、そしてあなたがHashMapのからするオブジェクトを見つけていない、キーの変更を防ぐための時間に置く場合は、別のハッシュコードを返すと、キーを取得する必要があるため不変性が必要です。4、HashMapのは、どのようにハッシュ関数が達成されていますか?

私たちは、キーのハッシュ値に基づいて、配列内の対応する場所を得る必要がある、あなたは要素を検索するハッシュマップで見ることができます。これは、ハッシュアルゴリズムの位置を計算する方法です。前記データ構造に先行する配列とハッシュマップにリンクされたリストの組み合わせである、もちろん、我々は、これらの要素の位置が均一に分布することを望む各位置における要素の数は一つだけであるように、可能な限り、内部ハッシュマップ、我々はハッシュアルゴリズムを見つけたときときに、この位置は、すぐに私たちが何をしたいの対応する要素の場所を知っているし、リストを横断することはできません。したがって、我々は、最初の要素の分布が比較的均一になるように配列の長さは、モジュロ演算をハッシュコードと考えました。しかし、操作の消費量の「モード」は非常に大きい、速く見つけることができない、我々はJDK1.8のソースコードを見る方法で、より少ない消費(家主が少し変更された)それを行う方法であります

ハッシュ静的(オブジェクトキー)INT最終{ IF(キー== NULLの){ 0を返す; } int型Hを、H = key.hashCodeを();戻りハッシュ値がハッシュコードである@ ^:ビット単位のXOR //> >>:符号なし右シフトは、符号ビットは無視され、ギャップが充填されている0 // nは配列の長さ、すなわちアレイ部分的に初期化マップの長さであるリターン(N-1)・( H ^(H >>> 16 )); }

それは単にです

図1に示すように、同じ高16bt、低いおよび高い16ビットの16ビットは、排他的OR(バイナリ32ビット、16ビット前部16及び後部下側16ビットと16ビットに得られたハッシュコードが高いXORを行った)製

2、(N・1)&ハッシュ= - >得られた添字

5、あまりにも深い問題ではなく、なぜ二分探索木をジップの法則のリストをリードし、赤黒木を選択しますか?なぜ常に赤黒木を使用していませんか?

赤黒木は欠陥を解決するために二分探索木で選択した、例外的な場合でバイナリ検索ツリーは、(深い問題を引き起こし、リスト構造として元の使用、これに)線形構造になり、検索を横切りますそれは非常に遅くなります。新しいデータを挿入した後、赤、黒の木がバランスを維持するために、これらの操作の左回り、右利き、変色によって必要になることがあり、赤黒木の導入は、問題のクエリリストの深さを解決するために、データをすばやく見つけることです、我々は赤黒木は平衡二分木に属している知っています、しかし、「バランス」を維持するために支払う価格ですが、資源の損失のコストは、横断線形リストよりも少ないので、長さが8よりも大きい場合には、鎖長が非常に短い場合、それはない、赤黒木を使用します。私たちは、赤黒木を導入する必要がありますが、紹介が遅くなります。

6、赤黒木に関する意見について話?

1、非赤黒色で、すなわち各ノード

2、根は常に黒です

3.ノードが赤色である場合、その子ノードは(必ずしもその逆)黒でなければなりません

図4に示すように、各リーフノードは黒空のノード(NILノード)であります

5、从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)

7、解决hash 碰撞还有那些办法?

开放定址法。

当冲突发生时,使用某种探查技术在散列表中形成一个探查(测)序列。沿此序列逐个单元地查找,直到找到给定的地址。

按照形成探查序列的方法不同,可将开放定址法区分为线性探查法、二次探查法、双重散列法等。

下面给一个线性探查法的例子  

问题:已知一组关键字为(26,36,41,38,44,15,68,12,06,51),用除余法构造散列函数,用线性探查法解决冲突构造这组关键字的散列表。

解答:为了减少冲突,通常令装填因子α由除余法因子是13的散列函数计算出的上述关键字序列的散列地址为(0,10,2,12,5,2,3,12,6,12)。

前5个关键字插入时,其相应的地址均为开放地址,故将它们直接插入T[0],T[10),T[2],T[12]和T[5]中。

当插入第6个关键字15时,其散列地址2(即h(15)=15%13=2)已被关键字41(15和41互为同义词)占用。故探查h1=(2+1)%13=3,此地址开放,所以将15放入T[3]中。

当插入第7个关键字68时,其散列地址3已被非同义词15先占用,故将其插入到T[4]中。

当插入第8个关键字12时,散列地址12已被同义词38占用,故探查hl=(12+1)%13=0,而T[0]亦被26占用,再探查h2=(12+2)%13=1,此地址开放,可将12插入其中。

类似地,第9个关键字06直接插入T[6]中;而最后一个关键字51插人时,因探查的地址12,0,1,…,6均非空,故51插入T[7]中。

8、如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?

默认的负载因子大小为0.75,也就是说,当一个map填满了75%的bucket时候,和其它集合类(如ArrayList等)一样,将会创建原来HashMap大小的两倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这个过程叫作rehashing,因为它调用hash方法找到新的bucket位置。这个值只可能在两个地方,一个是原下标的位置,另一种是在下标为<原下标+原容量>的位置

9、重新调整HashMap大小存在什么问题吗?

当重新调整HashMap大小的时候,确实存在条件竞争,因为如果两个线程都发现HashMap需要重新调整大小了,它们会同时试着调整大小。在调整大小的过程中,存储在链表中的元素的次序会反过来,因为移动到新的bucket位置的时候,HashMap并不会将元素放在链表的尾部,而是放在头部,这是为了避免尾部遍历(tail traversing)。如果条件竞争发生了,那么就死循环了。(多线程的环境下不使用HashMap)为什么多线程会导致死循环,它是怎么发生的?HashMap的容量是有限的。当经过多次元素插入,使得HashMap达到一定饱和度时,Key映射位置发生冲突的几率会逐渐提高。这时候,HashMap需要扩展它的长度,也就是进行Resize。1.扩容:创建一个新的Entry空数组,长度是原数组的2倍。2.ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组。

如果你依然觉得有些茫然,不如跟有多年Java开发经验的资深工程师聊一聊。

每天2小时学习时间,密集输入Java开发相关知识及经验,帮你快速实现技术和职业成长上的突破。

只需要关注+转发+评论,然后私信我“教程”就可以获取了,方法很简单,就看自己怎么去把握了,看好你们哦!

 

おすすめ

転載: www.cnblogs.com/cold-windy/p/11504441.html