【问题标题】:Hash Map entries collision哈希映射条目冲突
【发布时间】:2015-08-17 09:36:58
【问题描述】:

我正在尝试这个代码 sn-p

Map headers=new HashMap();
headers.put("X-Capillary-Relay","abcd");
headers.put("Message-ID","abcd");

现在,当我为其中一个键执行get 时,它工作正常。 但是我在 Eclipse 调试器上看到了一个奇怪的现象。 当我调试并进入变量并首先检查 table 条目时,我看到了这个

->table
--->[4]
------>key:X-Capillary-Relay
...........

但是在第二行调试后我得到了

->table
--->[4]
------>key:Message-ID
...........

它不会创建新条目,而是覆盖现有密钥。对于任何其他键,不会发生这种覆盖。地图的大小显示为 2。get 适用于两个键。那么eclipse调试器中这种差异背后的原因是什么。是日食问题吗?或哈希问题。 2 个键的哈希码不同。

【问题讨论】:

  • 只要能用就没有问题,还是有?该映射不会为每个哈希值提供单独的存储桶,因此如果两者最终位于同一个存储桶中也没问题。此外,我很确定创建了一个新条目 - 否则您将如何从地图中检索这两个值?
  • 如果代码工作和哈希值不同但 Eclipse 调试器显示地图内容不正确,那么它似乎是调试器的问题。
  • 我建议把 HashMap 当作一个黑盒子——只要你明白它的作用,你就不需要了解它是怎么做的。 (但如果你使用任何对象作为键,请实现 hashCode() 和 equals())

标签: java eclipse dictionary hash hashmap


【解决方案1】:

密钥的hashCode 未按原样使用。

它应用了两种转换(至少基于 Java 6 代码):

static int hash(int h) {
    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}

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

由于 length 是 HashMap 的初始容量(默认为 16),因此两个键都为 4:

System.out.println (hash("X-Capillary-Relay".hashCode ())&(16-1));
System.out.println (hash("Message-ID".hashCode ())&(16-1));

因此,两个条目都存储在映射的同一存储桶中的链表中(table 数组的索引 4,正如您在调试器中看到的那样)。调试器仅显示其中一个的事实并不意味着另一个已被覆盖。意思是你看到了链表第一个Entry的key,每一个新的Entry都被添加到链表的头部。

【讨论】:

    猜你喜欢
    • 2011-06-24
    • 2014-05-10
    • 2021-04-13
    • 1970-01-01
    • 2018-07-02
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 2016-07-30
    相关资源
    最近更新 更多