在Hashmap中重新散列

时间:2013-09-26 06:30:05

标签: java

影响HashMap性能的初始容量和负载因子两个参数。 默认加载因子(.75)在时间和空间成本之间提供了良好的折衷。较高的值会减少空间开销,但会增加查找成本。

将项目添加到HashMap时,会根据其hashCode的值和HashMap的存储区大小将其分配给存储桶。 要识别任何哈希值,请使用key.hashCode()并执行一些操作:

Bucket (index) = HashMap.indexFor(HashMap.hash(key.hashCode()),
                                  entryArray.length)

当哈希映射中的条目数超过加载因子和当前容量的乘积时,哈希映射将被重新哈希(内部数据结构被重建),因此哈希映射具有大约两倍的桶数。

当您重新散列并将所有内容移动到新位置(存储桶等)时,旧元素也会再次重新散列并根据新的哈希码存储在新存储桶中。分配用于存储元素的旧空间是垃圾收集。

如果两个线程同时发现现在HashMap需要重新调整大小并且他们都试图重新调整大小可能会导致HashMap中的竞争条件。

在重新调整HashMap的大小的过程中,存储在链表中的存储桶中的元素在迁移到新存储桶时会按顺序颠倒,因为java HashMap不会追加新的在尾部的元素,而不是在头部附加新元素,以避免尾部遍历。如果发生竞争条件,那么你将最终得到一个无限循环。

我有以下问题:

  1. 为什么每个存储桶的链表在此期间按顺序颠倒 迁移到新桶?
  2. 竞争条件如何导致无限循环?
  3. 如何增加桶的数量会减少查找等待 时间?
  4. 同一个桶中的元素仍然在一起 在重组后斗?

2 个答案:

答案 0 :(得分:0)

这就是我们ConcurrentHashMap的原因。对于绝大多数情况,如果一个人没有在没有同步的情况下在多个线程上共享一个地图,那么普通的HashMap就足够了。

无法保证与 n 存储桶发生冲突的两个对象仍会与2 n 存储桶发生冲突。只使用计数参数,它应该是任何两个对象碰撞的可能性的一半。较少的碰撞意味着更短的列表,这意味着检索时间更短。

因为我们正在重复冲突并且冲突在不同数量的存储桶中不一致,所以当您断言每个存储桶的列表作为过程的一部分被反转时,我怀疑您正在正确读取代码。

答案 1 :(得分:0)

  1. 实施细节 - 我不知道 - 可能是出于性能原因。
  2. 我不知道它是否会导致无限循环,但由于HashMap中没有同步,因此它不是线程安全的,不管它如何中断并不是那么重要:它会以某种方式打破...... < / LI>
  3. 每个桶的最终产品数量减少 - 因此在给定存储桶中的项目搜索速度更快
  4. 不,这就是重复的重点。想象一下,例如一个简单的哈希算法index = hash % numberOfBuckets