【问题标题】:Why does HashMap.Entry class have a field for hash?为什么 HashMap.Entry 类有一个哈希字段?
【发布时间】:2018-03-31 12:12:33
【问题描述】:

当我们向 HashMap 添加条目或检索条目时,键上的 equals() 足以在存储桶的特定索引中找到它。为什么还要存储和检查哈希?

【问题讨论】:

  • 您如何仅使用equals() 找到存储桶?
  • 没有HashMap.Entry 类,是吗?

标签: java hashmap


【解决方案1】:

您是正确的,在执行查找和删除等操作时,无需重新计算键(在条目中)的哈希值。它们是出于性能相关的原因而存储的。

计算一个键的哈希值可能很昂贵。

当条目与主数组大小的比率超过某个值(“负载因子”)时,HashMap 实现会扩展数组。发生这种情况时,所有现有条目都需要重新分配到新的哈希链……基于条目键的值。哈希值存储在 Entry 对象中,因此每次需要重新分配条目时都不必重新计算它们。

已经存储了哈希码值,它们也可以用来加速查找......

// Version #1
if (node.key.equals(keyToTest)) {
    ...
}

// Versions #2
if (node.hashValue == hashValueToTest && node.key.equals(keyToTest)) {
    ...
}

如果key.equals 方法很昂贵,那么您可以通过避免在哈希值不匹配时调用它来节省一些时间(平均而言)。 (但是当他们确实匹配时,无论如何都必须进行调用!)


所以,实际上,存储哈希值有两个原因。

【讨论】:

    【解决方案2】:

    HashMapMap 的一个实现,它维护一个条目表,其中包含对相关键和值的引用,根据它们的哈希码进行组织。此实现为基本操作(get 和 put)提供恒定时间性能,假设哈希函数将元素正确地分散在桶中。

    请看:

    Hashmap and how this works behind the scene

    虽然equals() 足以(最终)找到密钥是正确的,但这不会提供恒定时间的性能。

    Map 的其他实现不使用哈希码。

    【讨论】:

    • 你说得对,原因是性能。从 CS 的角度来看,在 big-O 表示法中使用“equals”和“first test hashCode, then equals”没有区别。
    • @Jens 哈希码的主要原因是哈希表。
    • 你是对的?
    • @Jens 在 big-O 表示法中使用“equals”和“first test hashCode, then equals”可能没有区别,但首先检查哈希码通常会更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-03
    • 2020-11-16
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    • 2021-06-03
    • 2014-01-30
    相关资源
    最近更新 更多