java - 如果 HashMap 满了怎么办?

标签 java hashmap concurrenthashmap

我知道java Hashmap有一个容量和负载因子参数。所以,如果这个hashmap中的项目数量超过容量*负载因子,一个新的hashmap将被重建。我对重建有一些疑问它:

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

最佳答案

The previous hashmap will be reclaimed or still be in use if the reconstruction happened?

还是原来的hashmap,只是内部存储被重构了。重建后,不再需要旧的存储桶数组,可以对其进行GC。

更新:内部 HashMapNode<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来源和引用目前的tableget() 使用和一个可能的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/

相关文章:

java - 空大括号/大括号在 Java 中是什么意思?

java - 为什么 HashMap 重新散列键对象提供的散列码?

java - 组合 2 个 HashMap 并返回 String

scala - 你会如何用猫包装一个包含并发 HashMap 的类?

java - 并发 hashmap size() 方法复杂度

java - 如何交换两个圆

Emacs 中的 Java 模式参数缩进

c++ - hash_map 和 unordered_map 的区别?

java - ConcurrentHashMap JDK 8 何时使用 computeIfPresent

java - 在 Java 泛型中读写协变和逆变