根据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");
答案 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
类,它将键与其在同一对象中的值组合在一起,并将条目存储在存储桶中。