在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
    }
}

其他回答

你曾经存储空值吗?如果没有,你可以这样做:

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
    }
}

你是说你有代码

如果(map.containsKey(关键))doSomethingWith (map.get(关键))

到处都是?然后你应该简单地检查map.get(key)是否返回null,就是这样。 顺便说一下,HashMap不会因为缺少键而抛出异常,而是返回null。唯一需要使用containsKey的情况是存储空值,以区分空值和缺失值,但这通常被认为是不好的做法。

Jon Skeet的回答以一种有效的方式很好地解决了两种情况(映射为空值和非空值)。

关于数字条目和效率问题,我想补充一些东西。

我有一个HashMap,有1000个条目,我正在改进 的效率。如果HashMap被频繁访问,那么 在每个访问处检查密钥是否存在将导致一个较大的 开销。

一个有1000个条目的地图并不是一个巨大的地图。 还有一张有5000到10000个条目的地图。 地图是为实现快速检索而设计的。

现在,它假设映射键的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中使用,你可能会有一些冲突,但从1000到数千个对象在Map中,你应该有很少的对象,因为String. hashcode()方法提供了一个良好的分布。

如果使用自定义类型,则正确重写hashCode()和equals(),并确保hashCode()提供公平的分布。 你可以参考Java Effective的第9项。 这里有一篇文章详细介绍了这个方法。

更好的方法是使用HashMap的containsKey方法。明天有人会把null添加到Map中。您应该区分键是否存在和键是否有空值。

从java 1.8开始,你可以简单地使用:

var item = mapObject.getOrDefault(key, null);
if(item != null)