具有字节数组键和字符串值的 HashMap - containsKey() 函数不起作用
HashMap with byte array key and String value - containsKey() function doesn't work
我正在使用 HashMap:byte[] 键和字符串值。但我意识到即使我使用
放置相同的对象(相同的字节数组和相同的字符串值)
myList.put(TheSameByteArray, TheSameStringValue)
到HashMap中,table仍然插入一个新的对象,具有不同的HashMapEntry。然后函数 containsKey() 无法工作。
有人可以为我解释一下吗?我怎样才能解决这个问题?谢谢。 (Android 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;
}
A byte[]
(或任何数组)无法作为 HashMap
中的键正常工作,因为数组不会覆盖 equals
,因此将考虑两个数组仅当它们引用同一对象时才相等。
您必须将 byte[]
包装在一些覆盖 hashCode
和 equals
的自定义 class 中,并将该自定义 class 用作你的 HashMap 的关键。
添加到 Eran 的明确答案中,因为 byte[] 或任何数组都不会覆盖 hashcode 和 equals(它使用 Object class 的默认方法),你总是可以环绕一个字符串对象,它需要 byte[ ] 作为构造函数 argument.Not String 只在 Map 中形成好的键,它们也是不可变的(基于 Hash 的 map 中的操作更快)
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#String(byte[])
注意:这是一种在不重写 equals() 或 hashCode() 方法的情况下生成数组或字符串(HashMap 中的键)的极其 hack-y 的方法。
我将以通用的方式包含答案,以便读者可以根据他们的要求了解并实施。
比如说,我有两个号码,n
和 r
。我想要一个以 [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)
将为真。
注意:这不是一个好方法。这只是一种解决方法。
您可以使用 ByteBuffer
,它是带比较器的 byte[] 数组的包装器。
参考答案来自 -
我正在使用 HashMap:byte[] 键和字符串值。但我意识到即使我使用
放置相同的对象(相同的字节数组和相同的字符串值)myList.put(TheSameByteArray, TheSameStringValue)
到HashMap中,table仍然插入一个新的对象,具有不同的HashMapEntry。然后函数 containsKey() 无法工作。
有人可以为我解释一下吗?我怎样才能解决这个问题?谢谢。 (Android 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;
}
A byte[]
(或任何数组)无法作为 HashMap
中的键正常工作,因为数组不会覆盖 equals
,因此将考虑两个数组仅当它们引用同一对象时才相等。
您必须将 byte[]
包装在一些覆盖 hashCode
和 equals
的自定义 class 中,并将该自定义 class 用作你的 HashMap 的关键。
添加到 Eran 的明确答案中,因为 byte[] 或任何数组都不会覆盖 hashcode 和 equals(它使用 Object class 的默认方法),你总是可以环绕一个字符串对象,它需要 byte[ ] 作为构造函数 argument.Not String 只在 Map 中形成好的键,它们也是不可变的(基于 Hash 的 map 中的操作更快)
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#String(byte[])
注意:这是一种在不重写 equals() 或 hashCode() 方法的情况下生成数组或字符串(HashMap 中的键)的极其 hack-y 的方法。 我将以通用的方式包含答案,以便读者可以根据他们的要求了解并实施。
比如说,我有两个号码,n
和 r
。我想要一个以 [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)
将为真。
注意:这不是一个好方法。这只是一种解决方法。
您可以使用 ByteBuffer
,它是带比较器的 byte[] 数组的包装器。
参考答案来自 -