HashMap原理の詳細

4779 ワード

hashMapは何ですか
HashMapはJavaでよく使われているキーパッドのデータ構造で、スレッドが安全ではないので、nullキーの値を保存できます。これらはよく使われています。
一、原理を実現する
HashMapは配列ハッシュ+チェーン表を用いてキーペアを格納し、キーペアのオブジェクトは次のように実現される。
   static class Entry<K,V> implements Map.Entry<K,V> {  
      final K key;  
     V value;  
      Entry next;  
      final int hash;  
    ……  
}  
一つのEntryの配列テーブルを通して複数のオブジェクトの保存を実現し、ハッシュ値とキー値を使って挿入と検索の衝突を解決しました。
一、putメソッドは、キーのペアに書き込みます。
public V put(K key, V value){

 //   key   null,   putForNullKey     null   
 if (key == null){
    return putForNullKey(value);
}

//   key   keyCode    Hash   
int hash = hash(key.hashCode());
//  hash  table    
int i = indexFor(hash, table.length);
//    i      Entry    null,                     key Entry
for (Entry e = tablei; e != null; e = e.next) {
    Object k;
    //        key hash   Entry
    if (e.hash == hash && ((k = e.key) == key|| key.equals(k)){

        //key        value ,    
    V oldValue = e.value;
      e.value = value;
    e.recordAccess(this);
  return oldValue;
        }
    }
//    i      Entry   null   key hash    key    ,     Entry
modCount++; 
//   key、value     i    
addEntry(hash, key, value, i); 
return null; 
} 
put方法でhash衝突を解決する方法ははっきりしています。つまり、2つのentryのhash値が同じであるとき、key値が同じかどうかを判断する必要があります。keyとhashは同じでなければ、修正できません。
addEntryの実現
コード:
void addEntry(int hash, K key, V value, int bucketIndex) 
{ 
  //      bucketIndex      Entry
Entry e = tablebucketIndex;  

tablebucketIndex = new Entry(hash, key, value, e); 
     //    Map    key-value          if (size++ >= threshold) 

     resize(2  table.length);

}  
新しいEntryを作成するには、テーブルのbucketIndexに要素があれば、作成時にイベントのnextを元の記憶要素に設定する必要があります。
二、get方法public V get(Object key)
{
// key null, getForNullKey null value
if (key == null)
return getForNullKey();
// key hashCode hash
int hash = hash(key.hashCode());
// table ,
for (Entry e = table[indexFor(hash, table.length)];
e != null;
// Entry
e = e.next)
{
Object k;
// Entry key hash key
if (e.hash == hash && ((k = e.key) == key
|| key.equals(k)))
return e.value;
}
return null;
}
によって実現される原理はgetと同じである。
三、注意すべき点
  • は、hash Mapの原理により、主な格納はhash値の計算に依存するので、Stringを選択すると、IntegerなどをキーにするとhashMapの効率が向上します。StringなどのオブジェクトがMapに入れば変化しないので、hash値も変わらず、取得対象の速度が大幅に向上します。
  • HashMapのサイズが負荷係数定義の容量を超えている場合、HashMapは元の2倍のbucket配列を作成し、元のオブジェクトを新しい配列に入れて、hashMapの容量を拡大する。(負荷係数初期0.75)
  • は、複数のスレッドで同時にHashMapのサイズが小さいことを発見し、サイズの調整を試み、条件競争を引き起こす。
  • は、Java 8において、hashと同じkeyの数が8より大きい場合、チェーンの代わりにバランスツリーを使用する。
  • HashMapはなぜスレッドが不安定ですか?
  • 上記のように、二つのスレッドが同時にHashMapの拡張を試みる時、一つのチェーンをリング状のチェーンテーブルに形成するかもしれません。すべてのnextは空ではなく、デッドサイクル
  • に入ります。
  • は、2つのスレッドが同時にputされると、1つのスレッドデータが失われる可能性がある