为什么整数键在HashMap中不起作用?

时间:2013-10-22 07:54:34

标签: java hashmap hashcode

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返回值。

5 个答案:

答案 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;
    }

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