HashMap以null作为键

时间:2014-09-06 06:43:19

标签: java hashmap

HashMap如何在内部区分null0作为关键字。

根据此postnull密钥的哈希码为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

4 个答案:

答案 0 :(得分:4)

  

如果是,那么两者都应该在索引0 ...

的同一桶中

正确。

  

并且HashMap中应该有一个值

不正确的。这两个键将有一个separsate条目。这由MapHashMap规范保证;即javadocs 每个不同的密钥都有一个单独的条目。实现 required 以满足规范......而且确实如此。

在Java 8之前,HashMap处理冲突的方式是将链接在一起散列到同一个存储桶的所有条目。 HashMap.get(key)逻辑将迭代相关存储桶的链,查找与密钥匹配的条目。 (在您的示例代码中,nullInteger(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中给定Entryhash的{​​{1}}值。< / p>