問題の説明:
Jdk1.7では、HashMapの拡張メカニズムは「ヘッド挿入方式」を採用しています。つまり、要素ハッシュが新しい配列スロットに到達すると、リンクされたリストの先頭に挿入されます。その理由は、テールに要素を追加し、時間の複雑さをO(n)にし、ヘッドを挿入するとパフォーマンスが向上するからです。
HashMapはスレッドセーフではないことはわかっていますが、このように書くと、同時に展開(サイズ変更)するときに閉ループリンクリストの問題が発生します。
理由分析:
void resize(int newCapacity){ Entry [] oldTable = table; int oldCapacity = oldTable.length; if(oldCapacity == MAXIMUM_CAPACITY){ threshold = Integer.MAX_VALUE; 戻る; } Entry [] newTable = new Entry [newCapacity]; transfer(newTable、initHashSeedAsNeeded(newCapacity)); table = newTable; しきい値 =(int)Math.min(newCapacity * loadFactor、MAXIMUM_CAPACITY + 1); } / ** *現在のテーブルからnewTableにすべてのエントリを転送します * / Void transfer(Entry [] newTable、boolean rehash){ int newCapacity = newTable.length; for(Entry <K、V> e:table){ while(null!= 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 = 次; } } }