Hashmap1.7ソースコード分析

データ構造

HashMap 採用されたデータ構造=配列(メイン)+単一リンクリスト(サブ)

HashMapの主な構造は配列に似ています。値を追加する場合、格納場所はキーによって決定されます。各場所はエントリデータ構造です。この構造はリンクリストを形成できます。競合が発生すると、同じハッシュ値のキーと値のペアがリンクリストを形成します。 。

この配列+リンクリストの組み合わせは、ほとんどの場合に良好なパフォーマンスを発揮します。Java6と7はこのように設計されていますが、極端な場合、一連の(慎重に設計された)キーと値のペアが発生しました。競合が発生した場合、この時点でのハッシュ構造はリンクリストに縮退し、HashMapのパフォーマンスが大幅に低下します。

 

 

 

putメソッド

 / ** 
  *指定された値をこのマップ内の指定されたキーに関連付けます。
  *マップに以前にキーのマッピングが含まれていた場合、古い
  値が*置き換えられます。
  * 
  * @paramの指定された値が関連付けられるキーキー
  * @paramのキー指定に関連付けられる値値
  *を@return <TT>キー</ TT>に関連付けられた以前の値、または
  * <TT>ヌル</ tt> <tt> key </ tt>のマッピングがなかった場合。
  *(<tt> null </ tt>の戻り値は、マップが
  以前に<tt> null </ tt>を<tt> key </ tt>に関連付けていたことを示すこともできます。
  
 V put(K key、V value){
     // 配列が空の場合、初期化を実行します。
     if(table == EMPTY_TABLE){
          inflateTable(threshold); 
     } 
     if(key == null // キーが空の場合、値を配列の位置0に移動し、
         return putForNullKey(value );
       // キーのハッシュ値を計算する
     int hash = hash(key);
      // ハッシュ値とデータを格納する配列の長さに基づいて位置インデックスを計算する
     int i = indexFor(hash、table.length);
      // 対応する位置にあるかどうかを調べる値は、値が新しい値に置き換えられた場合
     のために(エントリ<K、V>表E = [I] ;! E = NULL ; E = e.next){
         オブジェクトk;
         if(e.hash == hash &&((k = e.key)== key || key.equals(k))){ 
             V oldValue = e.value; 
             e.value = value;
              // HashMap空の実装、無視できる 
             e.recordAccess(this );
              return oldValue; 
         } 
     } 
     // レコードの変更時間に1を加えた 
     modCount ++ ;
      // キーと値のマッピングを配列に追加
     addEntry(hash、key、value、i);
      return  null ; 
 }

配列メソッドinflateTableを初期化する

/ ** 
  *テーブルをインフレートします
  * / 
 Private  void inflateTable(int toSize){
      // 2のべき乗を見つける> = toSize // toSizeよりも大きい
     2 の最小のべき乗を
      見つけます(例:toSize = 23、次に容量) 2 ^ 6 = 32 int capacity = roundUpToPowerOf2(toSize);
      // 容量と負荷係数に従って拡張しきい値を計算します。容量がこのしきい値に達すると、HashMapが容量を拡張します。
     threshold =(int)Math.min(capacity * loadFactor、MAXIMUM_CAPACITY + 1 );
      // EntiEntry <K、V> []配列ストレージサイズ 
     テーブルを初期化 = new Entry [capacity];
      // HashSeed 
     initHashSeedAsNeeded(capacity); 
 }を初期化

 お振込方法

void transfer(Entry [] newTable、boolean rehash){
         int newCapacity = newTable.length;
        for(Entry <K、V> e:table){
             whilenull!= e){ 
                Entry <K、V> next = e.next;
                if (rehash){ 
                    e.hash = null == e.key?0 :hash(e.key); 
                } 
                int i = indexFor(e.hash、newCapacity); 
                e.next = newTable [i]; 
                newTable [i] =e; 
                e = 次; 
            } 
        } 
    }

 このコードはHashMap拡張操作であり、各バケットの添え字を再配置し、ヘッド補間を使用して要素を新しい配列に移行します。ヘッド補間法は、リンクされたリストの順序を逆にします。これは、無限ループを形成するための重要なポイントでもあります。ヘッドの挿入方法を理解したら、エンドレスループとデータ損失を引き起こす方法を見下ろし続けます。

 

 

 

 

 

 

 

 

 

 

 

 

https://blog.csdn.net/carson_ho/article/details/79373026

https://cloud.tencent.com/developer/article/1489931

https://www.nowcoder.com/discuss/151172

https://www.cnblogs.com/yangyongjie/p/11015174.html

 

おすすめ

転載: www.cnblogs.com/dingpeng9055/p/12449584.html