HashMap中的键存在检查
检查HashMap中的键存在是否必要?HashMap中的键存在检查
我有一个HashMap说1000个条目,我期待提高效率。 如果HashMap被非常频繁地访问,那么在每次访问时检查密钥是否存在都会导致很大的开销。相反,如果钥匙不存在,并因此发生异常,我可以捕捉到异常。 (当我知道这很少会发生)。这将使对HashMap的访问减少一半。
这可能不是一个好的编程习惯,但它会帮助我减少访问次数。或者我在这里错过了什么?
[更新]我在HashMap中没有空值。
你曾经存储过空值吗?如果没有,你可以这样做:
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
}
}
我通常使用成语
Object value = map.get(key);
if (value == null) {
value = createValue(key);
map.put(key, value);
}
这意味着如果你丢失了钥匙,你只能打两次地图
你的意思是,你有这样的代码
if(map.containsKey(key)) doSomethingWith(map.get(key))
所有的地方?那么你应该简单地检查map.get(key)
是否返回null,就是这样。顺便说一下,HashMap不会为丢失的键引发异常,而是返回null。唯一需要containsKey
的情况是当你存储空值时,区分空值和缺失值,但这通常被认为是不好的做法。
通过检查密钥是否存在不会获得任何结果。这是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源代码。
资源:
显示这些方法的一个具体实现的重点是什么? – jarnbjo 2010-09-02 12:37:45
为了解释在大多数情况下,检查密钥是否存在与获取值大致相同。因此,在获取值之前,它不会优化检查密钥的实际存在。我知道这是一个泛化,但它可以帮助理解。 – 2010-09-02 12:42:54
一个很好的链接是http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashMap.java(OpenJDK非常强大的从Sun代码派生而来),似乎我错了。我正在比较Java5和Java6的版本;他们在这方面的工作方式不同(但都是正确的,因为您发布的片段)。 – 2010-09-02 15:02:41
- 如果重点班是你的确保的hashCode()和equals( ) 方法 实现。
- 基本上对HashMap的访问应该是O(1),但如果使用错误的hashCode方法实现,它将变成O(n),因为具有相同散列键的值将存储为链接列表。
为了清楚起见,仅使用containsKey()
。它速度很快,并保持代码清洁和可读。 HashMap
s的整点是密钥查找速度很快,只要确保hashCode()
和equals()
正确实施。
if(map.get(key) != null || (map.get(key) == null && map.containsKey(key)))
The Jon Skeet answer地址以及这两种情况(地图null
值和不null
值)的有效方法。
关于数字条目和效率问题,我想添加一些内容。
我有一个HashMap说一个1.000条目,我期待在提高 的效率。如果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
使用,您可能会遇到一些碰撞,但在Map
中有1000个到几千个对象,因此String.hashCode()
方法提供了良好的分布,所以您应该只有很少的几个对象。
如果您使用自定义类型,请正确覆盖hashCode()
和equals()
,并确保整体hashCode()
提供公平分配。
您可能会参考Java Effective
的第9项提到它。
这是一个post详细的方式。
“因此发生异常” - 什么异常?这不是来自java.util.HashMap ... – serg10 2010-09-02 12:06:49