如果HashMap已满,该怎么办?

wuc*_*ang 2 java hashmap concurrenthashmap

我知道java Hashmap有一个容量和加载因子参数.所以,如果这个hashmap中的项目数超过capacity*load factor,那么将重建一个新的hashmap.我对它的重构有一些疑问:

  1. 如果重建发生,之前的hashmap将被回收或仍然在使用?
  2. 既然我们需要更大尺寸的hashmap,那么哈希函数会被改变吗?
  3. 对于ConcurrentHashMap,如果一个线程正在插入(of cource,这个插入操作导致重构)而另一个线程正在读取怎么办?例如,它将从旧的hashmap还是从新的hashmap读取?

Tho*_*mas 9

如果重建发生,之前的hashmap将被回收或仍然在使用?

它仍然是相同的hashmap,只是内部存储被重建.在重建之后,不再需要旧的桶阵列并且可以进行gc'ed.

更新:内部HashMapNode<K,V>[] table.在调整大小期间,将构造一个新数组,移动元素,然后table用新数组替换.在该操作之后,映射本身将不再引用旧数组,因此除非没有其他引用(由于table包是私有的,这是不可能的),因此它对于gc是可以忽略的.

既然我们需要更大尺寸的hashmap,那么哈希函数会被改变吗?

不,哈希函数不会改变.它通常不依赖于桶的数量,但生成的散列将被调整以获得正确的桶(例如,通过应用模数)

更新:HashMap计算桶索引,如下所示:(size - 1) & hash,hash是键的hashCode()方法的返回值,它不依赖于映射本身.

对于ConcurrentHashMap,如果一个线程正在插入(of cource,这个插入操作导致重构)而另一个线程正在读取怎么办?例如,它将从旧的hashmap还是从新的hashmap读取?

我必须在这里猜测(我稍后会查看代码)但我假设只要线程从旧存储桶读取它们仍将被使用并且稍后将被释放.

更新:我快速查看了ConcurrentHashMap源代码,并且提到了当前table使用的当前内容get()以及可能nextTable的调整大小操作的目标.在调整大小期间,元素被传送到nextTable并且在结束时table被设置为nextTable有效地切换表.

这意味着在调整大小期间仍然会读取旧表,并且在某些时候它会被替换.在插入操作期间,可能存在一些阻塞,例如通过使用同步块,尤其是在需要调整大小或已经执行调整大小时.

文档还暗示了这一点:

一个哈希表,支持检索的完全并发和更新的高预期并发性.

这意味着,get将不会阻止,但是put,remove可能会在某个时候阻塞.