我知道java有一个容量和负载因子parameter.So,如果这个Hashmap中的项数大于容量*负载因子,那么将重新构造一个新的hashmap。我对它的重新构造有一些疑问:
发布于 2014-11-13 08:56:17
如果重建发生,先前的hashmap将被回收,还是仍在使用?
它仍然是相同的hashmap,只是内部存储被重建。重建后,不再需要旧的桶阵列,可以进行gc‘’ed。
更新:内部HashMap有Node<K,V>[] table。在调整大小期间,将构造一个新数组,移动元素,然后用新数组替换table。在该操作之后,映射本身将不再引用旧的数组,因此除非没有其他引用(因为table是包私有的),否则gc是可以理解的。
既然我们需要更大的哈希映射,那么会改变哈希函数吗?
不,哈希函数不会改变。它通常不取决于桶的数量,但生成的散列将被调整以获得正确的桶(例如,通过应用模块)
Update:HashMap像这样计算桶索引:(size - 1) & hash,hash是键的hashCode()方法的返回值,它不依赖于映射本身。
对于ConcurrentHashMap,如果一个线程正在插入(当然,这个插入操作导致了重新构造)而另一个线程正在读取呢?例如,它将从旧的hashmap或新的hashmap读取?
我不得不在这里猜测(稍后我将查找代码),但我假设,只要线程从旧的桶中读取,它们将仍然在使用中,稍后将被释放。
更新:我快速查看了ConcurrentHashMap源代码,并引用了get()使用的当前table和可能的nextTable,后者是调整大小操作的目标。在调整元素大小时,将元素转移到nextTable,并在最后将table设置为nextTable,从而有效地切换表。
这意味着,在调整旧表的大小时,仍然会读取旧表,并且在某个时候会替换旧表。在插入操作期间,可能会出现一些阻塞,例如使用同步块,特别是在需要调整大小或已经执行的情况下。
这些文件也暗示了这一点:
一个哈希表,支持检索的完全并发性和更新的高期望并发性。
这意味着get不会阻塞,但是put、remove等可能会在某个时候阻塞。
发布于 2014-11-13 09:08:05
1)
HashMap的实例有两个影响其性能的参数:初始容量和负载因子。容量是哈希表中的桶数,初始容量只是哈希表创建时的容量。负载因子是衡量允许哈希表在其容量自动增加之前得到多满的度量。当哈希表中的条目数超过负载因子和当前容量的乘积时,重新哈希表(即重建内部数据结构),使哈希表具有大约两倍的桶数。
2)如果事先很好地了解大小,那么在构造map对象时最好创建散列表。
HashMap(int initialCapacity)发布于 2014-11-13 08:56:58
如果重建发生,先前的hashmap将被回收,还是仍在使用?
如果没有对以前的结构的引用,它们可以被垃圾收集。
既然我们需要更大的哈希映射,那么会改变哈希函数吗?
不完全同意。哈希仍然是一样的,只有哈希映射到桶的方式被改变。例如,在展开之前,散列27,103和32,504可能映射到同一个桶。扩张后,他们可能会映射到不同的桶。散列映射将在每个桶中包含更多的桶和更少的元素。
对于ConcurrentHashMap,如果一个线程正在插入(当然,这个插入操作导致了重新构造)而另一个线程正在读取,那么该怎么办?例如,它将从旧的hashmap或新的hashmap读取?
如果你在乎,那你就得用锁。使用ConcurrentHashMap是因为您希望并发。如果要在读和写之间进行可预测的排序,则必须对它们进行排序。即使没有重建,这也是事实。如果您同时进行读和写,则读可能反映或不反映写入。如果您在一个线程中进行写入,并在该写入返回之前从另一个线程发出一个读,那么该读可能反映也可能不反映所写的内容。ConcurrentHashMap给出了合理的结果,但是没有强制排序(怎么可能呢?)
https://stackoverflow.com/questions/26904689
复制相似问题