我对哈希映射的内部工作有点困惑。
我创建了一个默认容量为16的Hashmap,我的密钥类总是返回一个哈希码值1.所以当我将第13个元素输入到这个地图时,它会使地图大小加倍。
1.哈希映射中会有多少个桶?
2.哈希映射是否按需创建新存储桶(即当哈希码与任何现有存储桶的哈希码值不匹配时)?
答案 0 :(得分:3)
虽然时间有点晚,但这可能有助于其他用户寻找这个问题的答案。
从第一个问题开始,哈希映射中会有多少个桶? - 如果你在实例化HashMap时没有在构造函数参数中指定它,那么将有16个桶作为默认容量。
现在让我们来看第二个问题,即哈希映射是否按需创建新桶(即当哈希码与任何现有存储桶的哈希码值不匹配时)?强>
看看Hashmap的put方法here的实现会很有趣。
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K, V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
如果仔细观察,在put方法中调用接受键的hashmap作为参数的方法 hash 。这种方法的工作是防止质量差的哈希函数。在使用此 indexFor 方法之后,标识将插入元素的索引(存储区)。此方法返回的索引始终指向现有存储桶。因此,不存在密钥的哈希码指向不存在的存储桶的情况。
那么hashmap何时创建一个新的存储桶?它在javase docs中得到了很好的解释。
它说:&#34; HashMap的一个实例有两个影响其性能的参数:初始容量和负载因子。容量是哈希表中的桶数,初始容量只是创建哈希表时的容量。加载因子是在自动增加容量之前允许哈希表获取的完整程度的度量。当哈希表中的条目数超过加载因子和当前容量的乘积时,哈希表将被重新哈希(即,重建内部数据结构),以便哈希表具有大约两倍的桶数。 &#34;
希望有所帮助。
答案 1 :(得分:0)
当您使用默认容量(16)创建HashMap
时,可以使用16个桶创建它(即容量==桶数)。
当容量加倍时,桶的数量翻倍。
hashCode始终匹配某个现有存储桶,因为模数N(其中N是当前容量)应用于计算的哈希,以便找到它所属的存储桶。
答案 2 :(得分:0)
我更多来自C#,但Java与它非常相似:) 如果有任何错误,请原谅我。随意纠正它。
无法轻松告知可用存储桶的数量。它取决于地图中的元素数量(加载因子)。负载系数保持在总容量的75%左右。这与以下事实有关:如果存在两个相同的哈希值,则必须对其中一个进行重新哈希(以在地图中获得另一个位置) - &gt; 75%是性能和尺寸之间的良好权衡。每当超过75%时,尺寸加倍(即16%的75%为12;第13个元素的尺寸加倍)。无论如何,这也是第二个问题的答案。