Cobnsider以下代码:
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接口接收Object,而不是参数化类型。所以我期望任何对象都可以是一个键,但HashMap实现检查类型为equals,这对我来说是令人惊讶的。
自动装箱不是问题。我知道,1成为Integer,1L成为Long。但是他们有相同的哈希码。因此我认为任何实现Map#get都应该为具有相同哈希码的任何Object返回值。
答案 0 :(得分:5)
您输入1L(Long
)的密钥并获得1({{1}})的密钥。
他们不是一回事,所以要小心。
从put中移除L,或将L添加到get中。或者甚至更好,不要把它们写成原语并依靠自动装箱。
答案 1 :(得分:1)
推杆和得分之间存在类型不匹配。
这里发生的是AutoBoxing,Java会自动而不是通过Object
执行原语之间到其new()
等价物的转换,反之亦然,所以变为Integer
而另一个是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
答案 2 :(得分:1)
这是因为你在检索值时没有传递Long类型的键,而是一个整数。它们作为不同的对象自动装箱,因此不代表相同的密钥。
答案 3 :(得分: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;
}
答案 4 :(得分:-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;
}
所以在返回值之前用等号检查键。