HashMap中关键的存在检查
检查HashMap中关键的存在是否必要?
我有一个HashMap说1000条目,我正在提高效率。 如果HashMap被非常频繁地访问,那么在每次访问时检查密钥的存在将导致很大的开销。 相反,如果钥匙不存在,因此发生exception,我可以赶上例外。 (当我知道这很less会发生)。 这将使访问HashMap减less一半。
这可能不是一个好的编程习惯,但它会帮助我减less访问次数。 还是我在这里错过了什么?
[ 更新 ]在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 } }
通过检查密钥是否存在,您将不会获得任何收益。 这是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源代码。
资源:
-
HashMap源代码不好的一个 - HashMap源代码好的一个
更好的方法是使用HashMap的containsKey方法。 明天将向地图添加空值,您应该区分键和空值。
你的意思是说你有类似的代码
if(map.containsKey(key)) doSomethingWith(map.get(key))
到处都是 ? 那么你应该简单地检查map.get(key)
是否返回null,就是这样。 顺便说一下,HashMap不会抛出丢失键的exception,而是返回null。 唯一需要使用containsKey
的情况是在存储空值时区分空值和缺失值,但这通常被认为是不好的做法。
if(map.get(key) != null || (map.get(key) == null && map.containsKey(key)))
为了清楚起见,只需使用containsKey()
。 这是快速的,并保持代码清洁和可读性。 HashMap
的关键在于密钥查找速度很快,只要确保hashCode()
和equals()
都正确实现。
我通常使用这个成语
Object value = map.get(key); if (value == null) { value = createValue(key); map.put(key, value); }
这意味着如果钥匙丢失,您只能点击地图两次
- 如果key类是你的确保hashCode()和equals()方法的实现。
- 基本上对HashMap的访问应该是O(1),但是用错误的hashCode方法实现它将变成O(n),因为具有相同散列键的值将被存储为链接列表。
Jon Skeet的回答很好地解决了两种情况(具有null
值和非null
值的映射)。
关于数字条目和效率问题,我想添加一些东西。
我有一个1.000条目的HashMap,我期待提高效率。 如果HashMap被非常频繁地访问,那么在每次访问时检查密钥的存在将导致很大的开销。
有1000个条目的地图不是一个巨大的地图。
以及具有5.000或10.000条目的地图。
Map
的目的是使这种尺寸的快速检索。
现在,它假定hashCode()
提供了一个很好的分布。
如果您可以使用Integer
作为键types,那么执行此操作。
它的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; } ... }
如果是键值,则必须使用另一个内置types(例如Map
经常使用的内置types),可能会有一些冲突,但在Map
有一千到几千个对象,您应该只有很less的一些因为String.hashCode()
方法提供了一个很好的分布。
如果使用自定义types, hashCode()
正确覆盖hashCode()
和equals()
,并确保hashCode()
提供了一个公平分配。
你可以参考Java Effective
9项Java Effective
引用它。
这里有一个细节的方式。