当前位置: 首页 > 知识库问答 >
问题:

当使用map.get()时,使用javaMap.containsKey()是多余的吗?

高化
2023-03-14

一段时间以来,我一直想知道,在最佳实践中,是否可以避免在< code>java.util.Map上使用< code>containsKey()方法,而是对< code>get()的结果进行空检查。

我的理由是,对值进行两次查找似乎是多余的——第一次是对< code>containsKey()进行查找,然后再次对< code>get()进行查找。

另一方面,可能是大多数Map的标准实现缓存了最后的查找,或者编译器可以以其他方式消除冗余,并且为了代码的易读性,最好保持包含Key()部分。

我非常感谢您的评论。

共有3个答案

蒋乐意
2023-03-14

正如assylias指出的,这是一个语义问题。通常,Map.get(x) == null是您想要的,但是在某些情况下,使用containsKey很重要。

缓存就是这样一个例子。我曾经在一个Web应用程序中处理过一个性能问题,该应用程序经常查询其数据库,寻找不存在的实体。当我研究该组件的缓存代码时,我意识到如果cache.get(key)==null,它就是在查询数据库。如果数据库返回null(未找到实体),我们将缓存该键-

切换到containsKey解决了这个问题,因为映射到null值实际上意味着什么。到null的键映射与不存在的键具有不同的语义含义。

颛孙飞
2023-03-14

我认为这样写是相当标准的:

Object value = map.get(key);
if (value != null) {
    //do something with value
}

而不是

if (map.containsKey(key)) {
    Object value = map.get(key);
    //do something with value
}

它的可读性和效率都没有降低,所以我认为没有任何理由不这样做。显然,如果您的映射可以包含null,那么这两个选项就没有相同的语义。

弓明亮
2023-03-14

允许某些Map实现具有空值,例如HashMap,在这种情况下,如果get(key)返回null,则不能保证map中没有与此键关联的条目。

因此,如果您想知道映射是否包含键,请使用< code>Map.containsKey。如果您只需要映射到键的值,请使用< code>Map.get(key)。如果这个映射允许null值,那么null的返回值不一定表示这个映射不包含这个键的映射;在这种情况下,< code>Map.containsKey没有用,并且会影响性能。此外,在并发访问映射(例如< code>ConcurrentHashMap)的情况下,在您测试了< code > map . contains key(key)之后,在您调用< code>Map.get(key)之前,该条目可能会被另一个线程删除。

 类似资料:
  • 问题内容: 我一直想知道,在最佳实践中,是否允许不使用on方法,而是对from的结果进行空检查。 我的理由是,重复两次查找值似乎是多余的:首先对进行查找,然后对进行查找。 另一方面,可能是大多数标准实现都缓存了最后一次查找,或者编译器可以通过其他方式消除冗余,并且对于代码的可读性而言,最好保留该部分。 非常感谢您的评论。 问题答案: 一些Map实现被允许具有空值,例如HashMap,在这种情况下,

  • 假设我有以下基类: 如果我想编写一个类,它将覆盖< code>f()并且不允许覆盖它的派生类,可以使用以下方法编写它: 方法一: 方法2: < code >方法1非常详细,而< code >方法2更加紧凑,并且< code>final仍然表示< code>f()实际上是虚拟的,并且覆盖了基类方法。 哪一种方法更合适?

  • 我看到了这个线程:servlet3.0中的java-async vs servlet3.1中的NIO,但它似乎涉及到servlet3.1NIO(与Tomcat NIO HTTP连接器相反)。 根据我的理解,使用NIO HTTP connectors实现(Tomcat 8及更高版本中的默认值)配置Tomcat处理请求和生成响应的实际工作是在单独的工作线程上完成的,读/写数据的轮询器线程保持畅通。 这

  • 问题内容: 基本上,我有一堆数据,其中第一列是字符串(标签),其余列是数值。我运行以下命令: 这样可以很好地读取大多数数据,但是label列只是获取“ nan”。我该如何处理? 问题答案: 默认情况下,使用:这就是将字符串列转换为NaN的原因,因为毕竟它们不是数字… 您可以使用以下方法来尝试猜测列的实际类型: 您可以使用它们的名称访问列,例如… 如果您不知道列应该是什么,那么使用是一个好技巧。如果

  • 当我使用时,我得到一个KeyError,同时构建我的pyplay程序。我为什么会得到这个,我该如何修复它? 我的设置。具体如下:

  • 我正试图将文件从本地目录复制到windows框上的网络共享。我使用的是jcifs 1.3.17。我成功地获得了到目标的连接,实际上在那里创建了文件,获得了“canwrite”状态为“true”,但是当我试图将本地文件的内容复制到远程文件时,我得到了以下错误: 代码段: 我不明白...如果我可以在目标上创建文件,并且smb看到我可以写到它,为什么doCopy会失败?