[英]Key existence check in HashMap
Is checking for key existence in HashMap always necessary?是否始终需要检查 HashMap 中是否存在密钥?
I have a HashMap with say a 1000 entries and I am looking at improving the efficiency.我有一个 HashMap,比如有 1000 个条目,我正在考虑提高效率。 If the HashMap is being accessed very frequently, then checking for the key existence at every access will lead to a large overhead.
如果 HashMap 的访问非常频繁,那么每次访问都要检查 key 是否存在会导致很大的开销。 Instead if the key is not present and hence an exception occurs, I can catch the exception.
相反,如果密钥不存在并因此发生异常,我可以捕获异常。 (when I know that this will happen rarely).
(当我知道这种情况很少发生时)。 This will reduce accesses to the HashMap by half.
这将使对 HashMap 的访问减少一半。
This might not be a good programming practice, but it will help me reduce the number of accesses.这可能不是一个好的编程习惯,但它会帮助我减少访问次数。 Or am I missing something here?
还是我在这里遗漏了什么?
[ Update ] I do not have null values in the HashMap. [更新] 我在 HashMap 中没有 null 值。
Do you ever store a null value? 你有没有存储空值? If not, you can just do:
如果没有,你可以这样做:
Foo value = map.get(key);
if (value != null) {
...
} else {
// No such key
}
Otherwise, you could just check for existence if you get a null value returned: 否则,如果返回null值,则可以检查是否存在:
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
}
}
You won't gain anything by checking that the key exists. 通过检查密钥是否存在,您将无法获得任何收益。 This is the code of
HashMap
: 这是
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;
}
Just check if the return value for get()
is different from null
. 只需检查
get()
的返回值是否与null
不同。
This is the HashMap source code. 这是HashMap源代码。
Resources : 资源:
Better way is to use containsKey
method of HashMap
. 更好的方法是使用
HashMap
containsKey
方法。 Tomorrow somebody will add null to the Map. 明天有人会向地图添加null。 You should differentiate between key presence and key has null value.
您应该区分密钥存在和密钥具有空值。
Do you mean that you've got code like 你是说你有像这样的代码
if(map.containsKey(key)) doSomethingWith(map.get(key))
all over the place ? 到处都是 ? Then you should simply check whether
map.get(key)
returned null and that's it. 然后你应该简单地检查
map.get(key)
是否返回null,就是这样。 By the way, HashMap doesn't throw exceptions for missing keys, it returns null instead. 顺便说一下,HashMap不会为丢失的密钥抛出异常,而是返回null。 The only case where
containsKey
is needed is when you're storing null values, to distinguish between a null value and a missing value, but this is usually considered bad practice. 需要
containsKey
的唯一情况是当你存储空值时,要区分空值和缺失值,但这通常被认为是不好的做法。
Just use containsKey()
for clarity. 为清楚起见,只需使用
containsKey()
。 It's fast and keeps the code clean and readable. 它速度快,保持代码清洁和可读性。 The whole point of
HashMap
s is that the key lookup is fast, just make sure the hashCode()
and equals()
are properly implemented. HashMap
的重点是密钥查找速度快,只需确保正确实现hashCode()
和equals()
。
if(map.get(key) != null || (map.get(key) == null && map.containsKey(key)))
You can also use the computeIfAbsent()
method in the HashMap
class. 您还可以在
HashMap
类中使用computeIfAbsent()
方法。
In the following example, map
stores a list of transactions (integers) that are applied to the key (the name of the bank account). 在以下示例中,
map
存储应用于密钥的事务(整数)列表(银行帐户的名称)。 To add 2 transactions of 100
and 200
to checking_account
you can write: 要向
checking_account
添加2个100
和200
事务,您可以编写:
HashMap<String, ArrayList<Integer>> map = new HashMap<>();
map.computeIfAbsent("checking_account", key -> new ArrayList<>())
.add(100)
.add(200);
This way you don't have to check to see if the key checking_account
exists or not. 这样您就不必检查密钥
checking_account
存在。
computeIfAbsent()
. computeIfAbsent()
将返回键的值。 Really elegant! 真的很优雅! 👍
👍
I usually use the idiom 我通常使用这个成语
Object value = map.get(key);
if (value == null) {
value = createValue(key);
map.put(key, value);
}
This means you only hit the map twice if the key is missing 这意味着如果缺少密钥,则只会按两次地图
The Jon Skeet answer addresses well the two scenarios (map with null
value and not null
value) in an efficient way. Jon Skeet的答案很好地解决了两种情况(使用
null
值映射而非null
值)。
About the number entries and the efficiency concern, I would like add something. 关于数字条目和效率问题,我想补充一些东西。
I have a HashMap with say a 1.000 entries and I am looking at improving the efficiency.
我有一个HashMap,说有1000个条目,我正在寻求提高效率。 If the HashMap is being accessed very frequently, then checking for the key existence at every access will lead to a large overhead.
如果非常频繁地访问HashMap,那么在每次访问时检查密钥是否存在将导致很大的开销。
A map with 1.000 entries is not a huge map. 包含1.000个条目的地图不是一张巨大的地图。
As well as a map with 5.000 or 10.000 entries. 以及具有5.000或10.000条目的地图。
Map
are designed to make fast retrieval with such dimensions. Map
旨在使这种尺寸快速检索。
Now, it assumes that hashCode()
of the map keys provides a good distribution. 现在,它假设map键的
hashCode()
提供了良好的分布。
If you may use an Integer
as key type, do it. 如果您可以使用
Integer
作为密钥类型,请执行此操作。
Its hashCode()
method is very efficient since the collisions are not possible for unique int
values : 它的
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;
}
...
}
If for the key, you have to use another built-in type as String
for example that is often used in Map
, you may have some collisions but from 1 thousand to some thousands of objects in the Map
, you should have very few of it as the String.hashCode()
method provides a good distribution. 如果为重点,你必须使用另一种内置类型
String
,例如,往往是在使用Map
,你可能会有一些冲突,但在1万到几千中的对象的Map
,你应该很少吧因为String.hashCode()
方法提供了良好的分布。
If you use a custom type, override hashCode()
and equals()
correctly and ensure overall that hashCode()
provides a fair distribution. 如果使用自定义类型,请正确覆盖
hashCode()
和equals()
,并确保hashCode()
提供公平分配。
You may refer to the item 9 of Java Effective
refers it. 您可以参考
Java Effective
9项Java Effective
引用它。
Here's a post that details the way. 这是一篇详细说明方式的帖子 。
Since java 1.8, you can simply use:从 java 1.8 开始,您可以简单地使用:
var item = mapObject.getOrDefault(key, null);
if(item != null)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.