4

参考以下代码:

public static void main (String[] args) {
    Map<Number, String> map = new HashMap<Number, String>();
    map.put(1L, "test");
    System.out.println(map.get(1));
}

为什么 HashMap.get 返回 null?O_o 它必须为 hashCode 函数返回 1 的任何对象返回值,不是吗?

更新

问题是 Map 接口接收对象,而不是参数化类型。所以我原以为任何对象都可以是key,但是HashMap实现用equals检查类型,这让我很吃惊。

自动装箱不是问题。我知道,那个 1 变成了 Integer,而 1L 变成了 Long。但是它们具有相同的哈希码。所以我认为任何实现 Map#get 都应该为具有相同哈希码的任何对象返回值。

4

5 回答 5

6

您正在输入 1L ( Long) 的键并获得 1 ( Integer) 的键。

它们不是一回事,所以要小心。

要么从 put 中删除 L,要么将 L 添加到 get。或者更好的是,不要将它们写成原语并依赖自动装箱。

于 2013-10-22T07:56:34.063 回答
1

put 和 getting 之间存在类型不匹配。

这里发生的是 AutoBoxing,Java 将自动执行原语与其Object等价物之间的转换,反之亦然,而不是通过new(), So becomeInteger和另一个 is Long

尝试以下方法:

public static void main (String[] args) {
        Map<Number, String> map = new HashMap<Number, String>();
        map.put(1L, "test");
        System.out.println(map.get(1L));
    }

或者

public static void main (String[] args) {
        Map<Number, String> map = new HashMap<Number, String>();
        map.put(1, "test");
        System.out.println(map.get(1));
    }

虽然两者都具有相同value的 (1) 但它们不是不同的对象equal

i.e. Integer(1) != Long(1).

这就是这里的问题,这是通过使用自动装箱发生的。

一个简单的例子

        Long l = new Long(1);
        Integer i = new Integer(1);
        System.out.println(i.equals(l)); //false -->Hashmap get() failed here
        System.out.println(i.intValue() ==l.intValue());//true
于 2013-10-22T07:56:33.067 回答
1

这是因为您在检索值时没有传递 Long 类型的键,而是一个整数。这些被自动装箱为不同的对象,因此不代表相同的键。

于 2013-10-22T07:57:10.277 回答
1

整数和长整数不一样。

Integer#equals

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

Long#equals

public boolean equals(Object obj) {
    if (obj instanceof Long) {
        return value == ((Long)obj).longValue();
    }
    return false;
}
于 2013-10-22T07:59:36.060 回答
-2

我发现了问题,请参阅 java.util.HashMap#get 源代码,它包含:

public V get(Object key) {
        if (key == null)
            return getForNullKey();
        int hash = hash(key.hashCode());
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

所以它在返回值之前用等号检查键。

于 2013-10-22T07:59:08.017 回答