如果HashMap已满,该怎么办?

时间:2014-11-13 08:50:42

标签: java hashmap concurrenthashmap

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

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

4 个答案:

答案 0 :(得分:9)

  

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

它仍然是相同的散列图,只是内部存储被重建。在重建之后,不再需要旧的桶阵列,并且可以是gc&#39。

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

  

因为我们需要一个更大的hashmap,所以,哈希函数会被改变吗?

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

更新HashMap计算存储区索引,如下所示:(size - 1) & hashhash是密钥hashCode()的返回值方法,它不依赖于地图本身。

  

对于ConcurrentHashMap,如果一个线程正在插入(对于cource,这个插入操作导致重构)并且另一个线程正在读取怎么办?例如,它将从旧的hashmap或新的hashmap读取? / p>

我必须在这里猜测(我稍后会查看代码)但我认为只要线程正在从旧存储桶中读取它们,它们仍将被使用并将被释放后面。

更新:我快速浏览了ConcurrentHashMap来源,并提及table使用的当前get()nextTable {1}}这是调整大小操作的目标。在调整大小期间,元素将传输到nextTable,最后table设置为nextTable,从而有效地切换表格。

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

文档还提示:

  

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

这意味着get不会阻止putremove等等。可能在某个时候阻止。

答案 1 :(得分:2)

From HashMap API

1)

  

HashMap的一个实例有两个影响其性能的参数:初始容量和负载因子。容量是哈希表中的桶数,初始容量只是创建哈希表时的容量。加载因子是在自动增加容量之前允许哈希表获取的完整程度的度量。 当哈希表中的条目数超过加载因子和当前容量的乘积时,哈希表将被重新哈希(即,重建内部数据结构),以便哈希表的数量大约是哈希表的两倍。水桶。

2)如果你事先知道大小,那么在构建地图对象时更好地创建hashbuckets。

HashMap(int initialCapacity)

答案 2 :(得分:0)

  

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

如果没有对先前结构的引用,则可以对它们进行垃圾回收。

  

因为我们需要一个更大的hashmap,所以,哈希函数会被改变吗?

不完全是。哈希仍然是相同的,只有哈希映射到桶的方式才会改变。例如,在扩展之前,散列27,103和32,504可以映射到同一个桶。扩展后,他们可能会映射到不同的桶。哈希映射将在每个存储桶中拥有更多存储桶和更少的元素。

  

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

如果您在意,那么您必须使用锁。您使用ConcurrentHashMap是因为您需要并发。如果要在读取和写入之间进行可预测的排序,则必须对它们进行排序。即使没有重建也是如此。如果您同时进行读写操作,则读取可能反映也可能不反映写入。如果在一个线程中写入并在该写入返回之前从另一个线程发出读取,则读取可能反映也可能不反映写入。 ConcurrentHashMap为您提供了理智的结果,但没有强制执行排序(怎么可能?)。

答案 3 :(得分:0)

  1. 以前将被垃圾收集
  2. 哈希函数不会改变,但哈希值(桶)可能因为哈希函数通常取决于哈希映射的大小
  3. hashmaps不是线程安全的。如果在线程之间共享散列图,则使用ConcurrentHashMap