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

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?它不是应该为任何hashCode函数返回1的对象返回值吗? 更新: 问题在于Map接口接收Object,而不是参数化类型。所以我期望任何对象都可以成为键,但HashMap实现使用equals检查类型,这让我感到惊讶。 自动装箱不是问题。我知道1变成了Integer,1L变成了Long。但它们具有相同的哈希码。所以我认为任何Map#get实现都应该为具有相同哈希码的任何对象返回值。

3
尝试使用 System.out.println(map.get(1L)); - Alexis C.
你说得对,整数1和长整数1L具有相同的哈希码,并将存储在映射内的同一个桶中。但是,一旦执行了.equals操作,它会返回false。 - Joop Eggen
5个回答

6
你把一个值为1L(Long)的键放进去,却得到一个值为1(Integer)的键。 它们并不是同一种类型,请小心。 可以从put中删除L,或在get中添加L。更好的做法是,不将它们写成原始类型,而是依赖于自动装箱。

2
不要使用HashMap<Number, String>,而是改用HashMap<Long, String>。 - TwoThe
@TwoThe 确实,我甚至没有注意到那个。 - Kayaman

1

放置和获取之间存在类型不匹配。

这里发生了自动装箱(AutoBoxing),Java会自动地在基本类型和其对应的Object类型之间进行转换,而不是通过new()方法。因此,int变成了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

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

1

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


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

因此,在返回值之前,它会先检查键是否相等。


1
java.util.HashMap#get有什么问题? - drndivoje
实际上,你的问题不在于 get。它的意思是为什么等式失败?这是因为 自动装箱 :) - Suresh Atta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,