【问题标题】:HashCode - What will happen if equal object happened to hash in the same bucket?HashCode - 如果相等的对象发生在同一个桶中散列会发生什么?
【发布时间】:2013-04-19 03:40:46
【问题描述】:

我知道这个问题已经被问过很多次了,但我找不到我的问题的确切答案。

在 Effective Java 的第 3 章中,有一个场景展示并解释了为什么哈希码应该与 equals 方法一起被覆盖。我了解了大部分内容,但其中有一部分我无法理解。

那里有一个给定的类,它覆盖了 equals 方法,但没有覆盖 hashCode 方法。对象作为键放在地图中

Map<PhoneNumber, String> m = new HashMap<PhoneNumber, String>();
m.put(new PhoneNumber(707, 867, 5309), "Jenny");

我知道如果我们 get 使用另一个相等对象 (m.get(new PhoneNumber(707, 867, 5309))),它将返回 null 仅仅是因为它们的哈希码不会被覆盖以返回相等对象的相等值(因为它会在另一个存储桶中搜索对象因为不同的哈希码)。

但根据我的理解,在那种情况下,不能保证两个对象的哈希码总是返回不同的。如果它们碰巧返回相同的哈希码怎么办?

我认为这部分解释了

即使两个实例碰巧哈希到同一个桶,get 方法几乎肯定会返回 null,因为 HashMap 有一个 缓存与每个条目关联的哈希码的优化和 如果哈希码不检查对象相等性,则不会打扰 匹配。

我只是没有得到缓存的东西。有人能详细解释一下吗?

另外,我已经做了功课,发现了一个相关的问题

Influence of HashMap optimization that caches the hash code associated with each entry to its get method

但我对接受的答案并不满意,而且回答者在评论中说

哈希码可以是任意整数,因此每个哈希码不能有 自己的桶。因此,一些具有不同哈希码的对象 最终在同一个桶中。

我完全不同意。据我了解,不同的哈希码永远不会出现在同一个存储桶中。

【问题讨论】:

    标签: java hashcode language-lawyer


    【解决方案1】:

    看看java.util.HashMap如何通过hashCode计算key的bucket号:

    /**
     * Returns index for hash code h.
     */
    static int indexFor(int h, int length) {
        return h & (length-1);
    }
    

    如果哈希表长度 = 16,那么 128 和 256 都将进入桶 #0。 Hashtable 是一个条目数组:

       Entry<K,V>[] table
       ...
       class Entry<K,V> {
               K key;
               V value;
               Entry<K,V> next;
               int hash;
        ...
    

    条目可以形成一个链(LinkedList)。如果桶#0 (table[0]) 为空(null) 则新条目将直接放在那里,否则HashMap 将找到链中的最后一个条目并设置最后一个条目的next = new entry。

    【讨论】:

      【解决方案2】:

      当说“即使两个实例碰巧散列到同一个桶”时,这并不意味着它们具有相同的散列码。甚至不同的哈希码也可以映射到同一个桶[阅读关于哈希]。

      因此,即使键散列到同一个存储桶,也可能不会为相关元素调用 .equals(由于缓存优化)(因为甚至散列码都不匹配)。因此,即使相关元素位于同一个桶中,也可能永远不会通过 .equals 进行比较,因此不会“找到”。

      【讨论】:

      • 您能否提供一个链接来证明即使是不同的哈希码也可以映射到同一个存储桶?对不起,如果我的理解可能不正确。
      • 这就是散列的工作原理。让我举一个简单的案例。假设我有 10 个桶,所以我必须在 10 个桶中容纳所有元素,所以找到桶的简单公式是: BucketNumber = hascode%10;现在 hascode 值 1 和 11 、 2 和 12 等将具有相同的桶号但不同的 hascode。这就是为什么 javadoc 声明具有相同 hascode 的 2 个元素可能相等也可能不相等。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-27
      • 2015-01-15
      • 1970-01-01
      • 2020-11-15
      • 1970-01-01
      • 2017-08-31
      • 1970-01-01
      相关资源
      最近更新 更多