8

我正在使用 HashMap: byte[] 键和 String 值。但我意识到,即使我通过使用放置相同的对象(相同的字节数组和相同的字符串值)

myList.put(TheSameByteArray, TheSameStringValue)

进入HashMap,表中仍然插入了一个具有不同HashMapEntry的新对象。然后函数 containsKey() 无法工作。

有人可以为我解释一下吗?我怎样才能解决这个问题?谢谢。(安卓Java)

@Override public boolean containsKey(Object key) {
    if (key == null) {
        return entryForNullKey != null;
    }

    int hash = Collections.secondaryHash(key);
    HashMapEntry<K, V>[] tab = table;
    for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
            e != null; e = e.next) {
        K eKey = e.key;
        if (eKey == key || (e.hash == hash && key.equals(eKey))) {
            return true;
        }
    }
    return false;
}
4

4 回答 4

7

A byte[](或任何数组)不能作为 a 中的键正常工作HashMap,因为数组不会覆盖equals,因此只有当两个数组引用同一个对象时,它们才会被视为相等。

您必须将您包装byte[]在一些覆盖hashCodeand的自定义类中equals,并将该自定义类用作 HashMap 的键。

于 2015-08-11T09:34:18.647 回答
1

注意:这是一种非常 hack-y 的方法,可以在不覆盖 equals() 或 hashCode() 方法的情况下创建数组或字符串,作为 HashMap 中的键。我将以通用的方式包含答案,以便读者可以根据他们的要求了解想法并实施。

说,我有两个数字,nr。我想要一个[n,r]作为键和(n+r)作为值的键值对。

Map<List<Integer>, Integer> map = new HashMap<List<Integer>, Integer>();

List<Integer> key = Arrays.asList(n, r);
if( map.containsKey(key) )
    return map.get(key);

如果地图不包含密钥怎么办?

map.put(Collections.unmodifiableList(Arrays.asList(n, r)), (n+r));

unmodifiable部分(无需深入探讨)确保密钥无法更改哈希码。

现在,map.containsKey(key)将是真的。

注意:这不是一个好方法。这只是一种解决方法。

于 2016-03-02T12:32:58.650 回答
1

您可以使用ByteBuffer,它是带有比较器的 byte[] 数组的包装器。

参考答案 - https://stackoverflow.com/a/14087243/4019660

于 2020-07-08T20:34:00.520 回答
1

添加到 Eran 的明确答案中,由于 byte[] 或任何数组都不会覆盖 hashcode 和 equals(它使用 Object 类的默认方法),您始终可以包装一个将 byte[] 作为构造函数参数的字符串对象。不仅字符串在 Map 中形成好的键,它们也是不可变的(基于哈希的映射中的操作更快)

http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#String(byte[])

于 2015-08-11T09:55:30.197 回答