【发布时间】:2018-03-31 12:12:33
【问题描述】:
当我们向 HashMap 添加条目或检索条目时,键上的 equals() 足以在存储桶的特定索引中找到它。为什么还要存储和检查哈希?
【问题讨论】:
-
您如何仅使用
equals()找到存储桶? -
没有
HashMap.Entry类,是吗?
当我们向 HashMap 添加条目或检索条目时,键上的 equals() 足以在存储桶的特定索引中找到它。为什么还要存储和检查哈希?
【问题讨论】:
equals() 找到存储桶?
HashMap.Entry 类,是吗?
您是正确的,在执行查找和删除等操作时,无需重新计算键(在条目中)的哈希值。它们是出于性能相关的原因而存储的。
计算一个键的哈希值可能很昂贵。
当条目与主数组大小的比率超过某个值(“负载因子”)时,HashMap 实现会扩展数组。发生这种情况时,所有现有条目都需要重新分配到新的哈希链……基于条目键的值。哈希值存储在 Entry 对象中,因此每次需要重新分配条目时都不必重新计算它们。
已经存储了哈希码值,它们也可以用来加速查找......
// Version #1
if (node.key.equals(keyToTest)) {
...
}
// Versions #2
if (node.hashValue == hashValueToTest && node.key.equals(keyToTest)) {
...
}
如果key.equals 方法很昂贵,那么您可以通过避免在哈希值不匹配时调用它来节省一些时间(平均而言)。 (但是当他们确实匹配时,无论如何都必须进行调用!)
所以,实际上,存储哈希值有两个原因。
【讨论】:
HashMap 是Map 的一个实现,它维护一个条目表,其中包含对相关键和值的引用,根据它们的哈希码进行组织。此实现为基本操作(get 和 put)提供恒定时间性能,假设哈希函数将元素正确地分散在桶中。
请看:
虽然equals() 足以(最终)找到密钥是正确的,但这不会提供恒定时间的性能。
Map 的其他实现不使用哈希码。
【讨论】: