HashMap
如何在内部区分null
和0
作为关键字。
根据此post,null
密钥的哈希码为0
,是否正确?
如果是,那么两者都应该在索引0
的同一个桶中,并且HashMap
中应该有一个值,但这不是HashMap
的工作方式。
有人可以解释一下吗? null
中的HashMap
键的哈希码是什么?
示例代码:
HashMap<Integer,String> map=new HashMap<Integer,String>();
map.put(null, "abc");
map.put(0, "xyz"); // will it override the value for null as key?
System.out.println(map.get(null)); // abc
System.out.println(map.get(0)); // xyz
答案 0 :(得分:4)
如果是,那么两者都应该在索引0 ...
的同一桶中
正确。
并且HashMap中应该有一个值
不正确的。这两个键将有一个separsate条目。这由Map
和HashMap
规范保证;即javadocs 说每个不同的密钥都有一个单独的条目。实现 required 以满足规范......而且确实如此。
在Java 8之前,HashMap
处理冲突的方式是将链接在一起散列到同一个存储桶的所有条目。 HashMap.get(key)
逻辑将迭代相关存储桶的链,查找与密钥匹配的条目。 (在您的示例代码中,null
和Integer(0)
键的链中会有单独的条目。)
在Java 8中,它的工作原理相同,但是对于密钥全部实现Comparable
并且链变得太长的情况进行了优化。在这种情况下,长链将转换为二叉树...以便O(N)
链扫描变为O(logN)
树搜索。
答案 1 :(得分:1)
这两种情况属于hashCode()==0
,但equals
不同,因此两个条目和get
都返回相关值。
案例为null:
public V put(null,"abc") {
if (key == null)
return putForNullKey(value);
}
private V putForNullKey(V value) {
..
addEntry(0, null, value, 0); ==> 0th index with 0 hashCode
return null;
}
案例0:
public V put(K key, V value) {
int hash = hash(key.hashCode()); ==> 0
int i = indexFor(hash, table.length); ==> 0
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { ==> false
..
}
}
modCount++;
addEntry(hash, key, value, i); ==> addition to link list
return null;
}
答案 2 :(得分:0)
哈希可能会有一些错误。
1,当键为0时,哈希码可能不为0.因为哈希码 是:
final int hash(Object k) {
int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
2,当你的密钥为空时,JDK调用一个特殊的方法来做,
if (key == null)
return putForNullKey(value);
是的,当key为null时,哈希值为0。 如果您想了解更多信息,请参阅JDK源代码。
答案 3 :(得分:0)
这是可能的,因为Entry
中的单个HashMap
不仅仅是键值对,而且还有next
字段,因此它是一种简单的链接列表,添加新条目如下:
void createEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<>(hash, key, value, e);
size++;
}
e
局部变量(已存在的变量)最终为next
中给定Entry
和hash
的{{1}}值。< / p>