hashmap 的 resize 方法的执行过程?
时间: 2023-05-03 21:00:17 浏览: 133
hashmap的resize方法是用来扩大或缩小哈希表的大小。具体实现过程是通过计算新的哈希表大小,并将原有的键值对重新散列到新的哈希表中。在扩大哈希表时,需要重新计算每个键的哈希值,并更新在新的哈希表里的位置。同时,扩大之后需要重新分配更多的内存,复制数据以及重新计算哈希值,因此resize操作的时间复杂度较高。
相关问题
hashmap的resize方法
HashMap的resize()方法是用于扩容HashMap的方法。当HashMap中存储的数据量大于threshold时或进行初始化HashMap时,会触发resize()方法进行扩容操作。\[1\]
在HashMap的putVal()方法中,会先判断table是否为空,如果为空,则会执行resize()方法进行初始化table。\[1\]
在HashMap中,当存储的数据量大于threshold时,也会执行resize()方法进行扩容操作。\[1\]
在JDK1.8之前,扩容操作在多线程情况下容易造成环形链表,可能导致get操作产生死循环。而在JDK1.8中,resize()方法不再调用transfer()方法,而是直接将原来transfer()方法中的代码写在自己的方法体内。此外,扩容后新数组中的链表顺序与旧数组中的链表顺序保持一致,不再改变顺序。\[2\]
#### 引用[.reference_title]
- *1* [最详细HashMap集合源码讲解(resize()方法)](https://blog.csdn.net/weixin_37541878/article/details/119391236)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item]
- *2* [HashMap的resize方法](https://blog.csdn.net/qq_38304320/article/details/103496039)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item]
[ .reference_list ]
HashMap 的 put 方法逻辑
HashMap 的 put 方法逻辑一般可以分为以下几个步骤:
1. 计算 key 的 hash 值:调用 key 的 hashCode 方法计算出 hash 值。
2. 计算数组下标:将 hash 值与 (数组长度 - 1) 进行按位与操作,得到数组下标。
3. 获取链表或红黑树头结点:根据数组下标获取对应的链表或红黑树的头结点。
4. 遍历链表或红黑树:遍历头结点对应的链表或红黑树,查找 key 是否已经存在。
5. 执行插入操作:如果 key 不存在,则将 key-value 对插入到链表或红黑树中。
6. 判断是否需要进行扩容:如果插入后元素个数大于等于阈值 (数组长度 * 负载因子),则进行扩容操作。
具体的 put 方法实现可以参考下面的代码:
```
public V put(K key, V value) {
// 计算 key 的 hash 值
int hash = hash(key.hashCode());
// 计算数组下标
int i = indexFor(hash, table.length);
// 获取链表或红黑树头结点
Entry<K,V> p = table[i];
// 遍历链表或红黑树
if (p == null) {
// 头结点为空,直接插入到链表中
table[i] = new Entry<>(hash, key, value, null);
} else {
// 头结点不为空,遍历链表或红黑树
Entry<K,V> e = p;
do {
if (e.hash == hash && (e.key == key || key.equals(e.key))) {
// key 已经存在,替换 value
V oldValue = e.value;
e.value = value;
return oldValue;
}
p = e;
e = e.next;
} while (e != null);
// 插入到链表的末尾
p.next = new Entry<>(hash, key, value, null);
}
// 插入成功,元素个数 + 1
size++;
// 判断是否需要进行扩容
if (size >= threshold) {
resize(2 * table.length);
}
return null;
}
```
阅读全文