如果发生重建,之前的 hashmap 会被回收还是仍在使用?
还是一样的hashmap,只是内部存储被重构了。重建后旧的桶数组不再需要,可以 gc'ed。
更新:内部HashMap 有Node<K,V>[] table。在调整大小期间,将构造一个新数组,移动元素,然后将table 替换为新数组。在该操作之后,地图本身将不再引用旧数组,因此除非没有其他引用(这不太可能,因为 table 是包私有的)它是符合 gc 的。
既然我们需要更大尺寸的hashmap,那么hash函数是否会改变?
不,哈希函数不会改变。它通常不依赖于桶的数量,但生成的哈希将被调整以获得正确的桶(例如通过应用模数)
更新:HashMap这样计算桶索引:(size - 1) & hash,hash是key的hashCode()方法的返回值,不依赖于map本身.
对于 ConcurrentHashMap ,如果一个线程正在插入(当然,这个插入操作导致了重新构造)而另一个线程正在读取呢?例如,它将从旧的 hashmap 中读取还是从新的 hashmap 中读取?
我不得不在这里猜测(我稍后会查找代码),但我假设只要线程正在从旧存储桶中读取,它们仍然会被使用并且稍后会被释放。
更新: 我快速浏览了ConcurrentHashMap 源,其中引用了get() 使用的当前table 和可能的目标nextTable用于调整大小操作。在调整大小期间,元素被转移到nextTable,最后table 设置为nextTable,有效地切换表。
这意味着在调整大小期间,旧表仍会被读取,并且在某些时候会被替换。在插入操作期间,可能会出现一些阻塞,例如通过使用同步块,尤其是在需要调整大小或已经执行调整大小时。
文档也暗示了这一点:
一个支持检索的完全并发和高预期更新并发的哈希表。
这意味着get 不会阻止,但put、remove 等。可能会在某个时候阻止。