# 老生常谈，HashMap的死循环

### 实现

HashMap的put方法实现：

1、判断key是否已经存在

``````public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
// 如果key已经存在，则替换value，并返回旧值
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}

modCount++;
// key不存在，则插入新的元素
return null;
}
``````

2、检查容量是否达到阈值threshold

``````void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {
resize(2 * table.length);
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
}

createEntry(hash, key, value, bucketIndex);
}
``````

3、扩容实现

``````void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
...

Entry[] newTable = new Entry[newCapacity];
...
transfer(newTable, rehash);
table = newTable;
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
``````

``````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 = next;
}
}
}
``````

### 案例分析

``````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 = next;
}
}
}
``````

``````Entry<K,V> next = e.next;
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
``````

1、执行完`Entry<K,V> next = e.next;`，目前节点a没有next，所以变量next指向null；
2、`e.next = newTable[i];` 其中 newTable[i] 指向节点b，那就是把a的next指向了节点b，这样a和b就相互引用了，形成了一个环；
3、`newTable[i] = e` 把节点a放到了数组i位置；
4、`e = next;` 把变量e赋值为null，因为第一步中变量next就是指向null；

END。

### 推荐阅读更多精彩内容

• Java8张图 11、字符串不变性 12、equals()方法、hashCode()方法的区别 13、...
Miley_MOJIE阅读 2,866评论 0 11
• 一、基本数据类型 注释 单行注释：// 区域注释：/* */ 文档注释：/** */ 数值 对于byte类型而言...
龙猫小爷阅读 3,281评论 0 16
• 5.1、对于HashMap需要掌握以下几点 Map的创建：HashMap() 往Map中添加键值对：即put(Ob...
rochuan阅读 187评论 0 0
• 是一颗孤伶的石头 他以为 是一粒遥远的星辰 夜了 一点荧荧 最不该 星零孕了诗心 诗心染了凡心 凡心动了春心 梦醒...
梦之i阅读 81评论 0 0