Java 如何以及何时在HashMap中进行重新灰化

Java 如何以及何时在HashMap中进行重新灰化,java,hash,hashmap,Java,Hash,Hashmap,我对散列和重新散列有些困惑。下面是我的理解,如果我错了,请纠正我 如图所示,bucket实际上是Entry类的数组,它以链表的形式存储元素。每个新的键值对(其键具有条目数组bucket的相同hashcode)将作为存储该hashcode元素的bucket中的条目对象存储。如果密钥具有当前不在条目数组bucket中的新hashcode,则将使用相应的hashcode添加一个新bucket 现在的问题是,实际上什么时候会发生再灰化 案例1:假设我有一个条目数组,在条目数组bucket达到12时添加了

我对散列和重新散列有些困惑。下面是我的理解,如果我错了,请纠正我

如图所示,bucket实际上是Entry类的数组,它以链表的形式存储元素。每个新的键值对(其键具有条目数组bucket的相同hashcode)将作为存储该hashcode元素的bucket中的条目对象存储。如果密钥具有当前不在条目数组bucket中的新hashcode,则将使用相应的hashcode添加一个新bucket

现在的问题是,实际上什么时候会发生再灰化

案例1:假设我有一个条目数组,在条目数组bucket达到12时添加了新元素,hashcode为1,2,3,但一旦出现一个hashcode为13的新元素(假设我在hashcode 1和2的序列中添加元素,以此类推),一个条目bucket的新映射/数组(请说明是哪一个)将被创建,新的容量将是32,现在条目数组可以容纳不同的32个存储桶

案例2:bucket dosent matter的数量,HashMap 16的默认容量意味着它可以在其中存储16个元素,dosent matter在单个bucket中或以任何方式存储。由于负载系数为.75,一旦添加了第13个元素,就会创建一个新的bucket数组,其中包含32个,即现在所有链接列表中的总入口节点可以是32个


我认为案例2是正确的。请规划重新散列过程,最好使用此图表。

重新散列会根据当前存储在
散列图中的条目数增加可用存储桶的数量

HashMap
实现确定应增加存储桶的数量以保持预期的
O(1)
查找和插入性能时,会发生此错误

关于.75默认加载因子以及它在添加第13个条目时如何使
HashMap
重新灰化,您是正确的


然而,HashMap 16的默认容量意味着它可以在其中存储16个元素,这是不正确的。任何bucket都可以存储多个条目。但是,为了保持所需的性能,每个bucket的平均条目数应该很小。这就是我们有加载因子的原因,也是我们应该使用适当的
hashCode()
将键尽可能均匀地分布在存储桶上的原因。

重新灰化是重新计算已存储项(键值对)的hashCode的过程,当达到负载因子阈值时,将它们移动到另一个更大的hashmap

当map中的项数超过负载因子限制时,hashmap将其容量加倍,并重新计算已存储元素的hashcode,以便在新存储桶中均匀分布键值对

为什么需要重新灰化

容量翻倍后,如何处理存储桶中已经存在的键值对

如果我们保持现有的键值对不变,那么将容量加倍可能没有帮助, 因为O(1)复杂性只有在项目均匀分布在所有存储桶中时才能实现

因此,对于每个现有的键值对,hashcode将使用增加的hashmap容量作为参数再次计算,这将导致将项目放置在同一个bucket中或不同的bucket中

重新灰化是为了在新的长度hashmap中分布项,以便get和put操作时间复杂性保持O(1)

注意:

Hashmap在向Hashmap中插入数据和从Hashmap中获取数据时保持O(1)的复杂性,但对于第13个键值对,put请求将不再是O(1),因为一旦map意识到第13个元素进入,即75%的map被填充

它将首先将存储桶(阵列)容量增加一倍,然后再进行重新存储。 重新分级需要重新计算已经放置的12个键值对的哈希代码,并将它们放在新索引中,这需要时间

你应该读一下这篇文章,它可能会有所帮助


如果我错了,请纠正我,你是说重新灰化取决于桶的数量,而不是元素的数量。问题-如果我输入10000。。。。元素,但所有元素的键的哈希代码都是相同的,即它将放在同一个桶中。不管我将输入多少个相同哈希代码的元素,都不会发生重新灰化。@shrikant.sharma这取决于存储桶的数量和条目的数量。在您的场景中肯定会发生重新格式化,但不会有多大好处,因为即使在重新格式化之后,由于相同的哈希代码,所有条目都将进入同一个存储桶。