HashMap中的密钥存在检查

时间:2010-09-02 11:45:16

标签: java hashmap

是否总是需要在HashMap中检查密钥是否存在?

我有一个HashMap,说1000条目,我正在寻求提高效率。 如果非常频繁地访问HashMap,那么在每次访问时检查密钥是否存在将导致很大的开销。相反,如果密钥不存在并因此发生异常,我可以捕获异常。 (当我知道这种情况很少发生时)。这将减少对HashMap的访问一半。

这可能不是一个好的编程习惯,但它会帮助我减少访问次数。或者我在这里遗漏了什么?

[更新]我在HashMap中没有空值。

10 个答案:

答案 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)

  1. 如果是关键类,请确保实现hashCode()和equals()方法。
  2. 基本上对HashMap的访问应该是O(1),但是使用错误的hashCode方法实现它会变成O(n),因为具有相同哈希键的值将存储为链接列表。

答案 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存储适用于密钥(银行帐户名称)的交易(整数)列表。要将100200的2个事务添加到checking_account,您可以编写:

HashMap<String, ArrayList<Integer>> map = new HashMap<>();
map.computeIfAbsent("checking_account", key -> new ArrayList<>())
   .add(100)
   .add(200);

通过这种方式,您不必检查键checking_account是否存在。

  • 如果它不存在,将由lambda表达式创建并返回一个。
  • 如果存在,则密钥的值将由computeIfAbsent()返回。

真的很优雅!