我知道java Hashmap有一个容量和负载因子参数。所以,如果这个hashmap中的项目数量超过容量*负载因子,一个新的hashmap将被重建。我对重建有一些疑问它:
- 如果发生重建,之前的 hashmap 会被回收还是仍然在使用?
- 由于我们需要更大尺寸的 hashmap,那么哈希函数会改变吗?
- 对于 ConcurrentHashMap 来说,如果一个线程正在插入(当然,这个插入操作导致了重新构造)而另一个线程正在读取,会怎样?例如,它会从旧的 hashmap 中读取,还是从新的 hashmap 中读取?里>
最佳答案
The previous hashmap will be reclaimed or still be in use if the reconstruction happened?
还是原来的hashmap,只是内部存储被重构了。重建后,不再需要旧的存储桶数组,可以对其进行GC。
更新:内部 HashMap
有Node<K,V>[] table
。在调整大小期间,将构造一个新数组,移动元素,然后 table
被替换为新数组。在该操作之后,映射本身将不再引用旧数组,因此除非没有其他引用(这不太可能,因为 table
是包私有(private)的),否则它适合 gc。
since we need a larger size hashmap , so , will the hash function be changed ?
不,哈希函数不会改变。它通常不依赖于存储桶的数量,但生成的哈希将被调整以获得正确的存储桶(例如通过应用模数)
更新:HashMap
像这样计算存储桶索引:(size - 1) & hash
, hash
是键的返回值hashCode()
方法,不依赖于 map 本身。
For ConcurrentHashMap , what if one thread is inserting(Of cource, this insert operation has lead to a re-construction) and another thread is reading?For example, it will read from the old hashmap or from the new hashmap?
我必须在这里猜测(我稍后会查找代码),但我假设只要线程从旧存储桶中读取它们,它们仍然会被使用,并且稍后会被释放。
更新:我快速浏览了 ConcurrentHashMap
来源和引用目前的table
由 get()
使用和一个可能的nextTable
这是调整大小操作的目标。在调整大小期间,元素将转移到 nextTable
最后table
设置为nextTable
,有效地切换表。
这意味着在调整大小期间,旧表仍会被读取,并且在某些时候它会被替换。在插入操作期间,可能会出现一些阻塞,例如通过使用同步块(synchronized block),特别是在需要或已经执行调整大小的情况下。
文档也暗示了这一点:
A hash table supporting full concurrency of retrievals and high expected concurrency for updates.
这意味着 get
不会阻止但 put
, remove
等等。可能在某个时刻阻塞。
关于java - 如果 HashMap 满了怎么办?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26904689/