IdentityHashMap是否会引发冲突?

时间:2012-10-08 09:43:52

标签: java data-structures

根据IdentityHashMap的{​​{3}},它说

  

该类使用哈希表实现Map接口   比较键时,引用相等性代替对象相等   (和价值观)。换句话说,在IdentityHashMap中,有两个键k1和   当且仅当(k1==k2)时,k2被认为是相等的。 (通常Map   实现(如HashMap)两个密钥k1和k2被认为是相等的   当且仅当(k1==null ? k2==null : k1.equals(k2))。)

据我所知,指向不同内存位置的两个不同对象仍然可以具有相同的哈希码,因此object1.equals(object2)可以返回true。 但是指向不同内存位置的两个不同对象永远不会返回true object1 == object2

问题1 - 当IdentityHashMap严格依赖于引用相等时,这是否意味着永远不会发生冲突?

问题2 - 调试以下代码显示了6个桶,其中键和值都存储在不同的存储桶中。但HashMap不是这种情况,其中键和值存储在同一个存储桶中。

因为它的名字中有一个'hash'字样,所以它必须对键进行散列,那么为什么它会分别存储键和值以及它如何检索给定键的值?

String A = "abc";
String B = "def";
String C = new String("abc");
Map<String, String> map1 = new IdentityHashMap<String, String>();
map1.put(A, "123");
map1.put(B, "345");
map1.put(C, "567");

3 个答案:

答案 0 :(得分:5)

IdentityHashMap不使用密钥的hashCode,而是System.identityHashCode。虽然如果你有一个巨大的内存,这种身份哈希码的冲突是可能的,但它们很少。这当然不会阻止两个密钥在同一个桶中结束,因为桶的数量通常远小于2 ^ 32 - 1。

答案 1 :(得分:3)

  

当IdentityHashMap严格依赖于引用相等时,这是否意味着永远不会发生冲突?

碰撞几乎就像没有碰撞一样。系统hashCodes不是唯一的,即使它们的集合大小也不是2 ^^ 32,因此只需要将hashCode减少到少量位。

  

如何检索给定密钥的值?

我会阅读代码以找出答案。

public V get(Object key) {
    Object k = maskNull(key);
    Object[] tab = table;
    int len = tab.length;
    int i = hash(k, len);
    while (true) {
        Object item = tab[i];
        if (item == k)
            return (V) tab[i + 1];
        if (item == null)
            return null;
        i = nextKeyIndex(i, len);
    }
}

答案 2 :(得分:1)

当两个不同的项具有相同的哈希码时发生冲突,因此显然IdentityHashMap必须处理冲突。唯一的区别是“常规”哈希映射使用equals对于不同对象可以true,而IdentityHashMap使用不能==的{​​{1}}对于不同的对象。

“常规”哈希映射具有单独的键和值变量的原因是true的实现细节:它的实现使用linear probing来解决冲突,它还存储键和值相同的表格:密钥位于IdentityHashMap,而值位于table[hash]。常规table[hash+1]定义了一个HashMap类,它将键与其在同一对象中的值组合在一起,并将条目存储在存储桶中。

相关问题