是否总是需要在HashMap中检查密钥是否存在?
我有一个HashMap,说1000条目,我正在寻求提高效率。 如果非常频繁地访问HashMap,那么在每次访问时检查密钥是否存在将导致很大的开销。相反,如果密钥不存在并因此发生异常,我可以捕获异常。 (当我知道这种情况很少发生时)。这将减少对HashMap的访问一半。
这可能不是一个好的编程习惯,但它会帮助我减少访问次数。或者我在这里遗漏了什么?
[更新]我在HashMap中没有空值。
答案 0 :(得分:482)
你有存储空值吗?如果没有,你可以这样做:
Foo value = map.get(key);
if (value != null) {
...
} else {
// No such key
}
否则,如果您返回空值,可以检查是否存在:
Foo value = map.get(key);
if (value != null) {
...
} else {
// Key might be present...
if (map.containsKey(key)) {
// Okay, there's a key but the value is null
} else {
// Definitely no such key
}
}
答案 1 :(得分:63)
通过检查密钥是否存在,您将无法获得任何收益。这是HashMap
的代码:
@Override
public boolean containsKey(Object key) {
Entry<K, V> m = getEntry(key);
return m != null;
}
@Override
public V get(Object key) {
Entry<K, V> m = getEntry(key);
if (m != null) {
return m.value;
}
return null;
}
只需检查get()
的返回值是否与null
不同。
这是HashMap源代码。
资源:
答案 2 :(得分:39)
更好的方法是使用HashMap的containsKey方法。明天soembody将向地图添加null,你应该区分key和key具有null值。
答案 3 :(得分:21)
你的意思是你有像
这样的代码
if(map.containsKey(key)) doSomethingWith(map.get(key))
到处都是?然后你应该只检查map.get(key)
是否返回null,就是这样。
顺便说一下,HashMap不会为丢失的密钥抛出异常,而是返回null。唯一需要containsKey
的情况是,当您存储空值时,要区分空值和缺失值,但这通常被认为是不好的做法。
答案 4 :(得分:7)
为了清楚起见,请使用containsKey()
。它速度快,保持代码清洁和可读性。 HashMap
s的重点是密钥查找速度很快,只需确保hashCode()
和equals()
得到正确实施。
答案 5 :(得分:4)
if(map.get(key) != null || (map.get(key) == null && map.containsKey(key)))
答案 6 :(得分:0)
我通常使用成语
Object value = map.get(key);
if (value == null) {
value = createValue(key);
map.put(key, value);
}
这意味着如果缺少密钥,您只会两次点击地图
答案 7 :(得分:0)
答案 8 :(得分:0)
The Jon Skeet answer以有效的方式很好地解决了两种情况(使用null
值而不是null
值的地图)。
关于号码条目和效率问题,我想补充一些内容。
我有一个HashMap,说有1000个条目,我正在寻求改进 效率。如果经常访问HashMap,那么 在每次访问时检查密钥存在将导致大的 开销。
包含1.000个条目的地图不是一张巨大的地图
以及包含5.000或10.000个条目的地图
Map
旨在快速检索此类维度。
现在,它假设地图键的hashCode()
提供了良好的分发。
如果您可以使用Integer
作为键类型,请执行此操作
其hashCode()
方法非常有效,因为唯一int
值不可能发生冲突:
public final class Integer extends Number implements Comparable<Integer> {
...
@Override
public int hashCode() {
return Integer.hashCode(value);
}
public static int hashCode(int value) {
return value;
}
...
}
如果对于密钥,您必须使用另一个内置类型String
,例如Map
中常用的内置类型,您可能会遇到一些冲突但从1千到几千个对象在Map
中,由于String.hashCode()
方法提供了良好的分布,因此您应该很少。
如果您使用自定义类型,请正确覆盖hashCode()
和equals()
,并确保hashCode()
提供公平分配。
您可以参考Java Effective
的第9项引用它
这是一个post详细说明的方式。
答案 9 :(得分:0)
您还可以在HashMap
类中使用computeIfAbsent()
方法。
在下面的示例中,map
存储适用于密钥(银行帐户名称)的交易(整数)列表。要将100
和200
的2个事务添加到checking_account
,您可以编写:
HashMap<String, ArrayList<Integer>> map = new HashMap<>();
map.computeIfAbsent("checking_account", key -> new ArrayList<>())
.add(100)
.add(200);
通过这种方式,您不必检查键checking_account
是否存在。
computeIfAbsent()
返回。 真的很优雅!