在使用 ConcurrentMap 的 putIfAbsent 之前,您是否应该检查地图是否包含密钥 [英] Should you check if the map containsKey before using ConcurrentMap's putIfAbsent

查看:29
本文介绍了在使用 ConcurrentMap 的 putIfAbsent 之前,您是否应该检查地图是否包含密钥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在将 Java 的 ConcurrentMap 用于可从多个线程使用的地图.putIfAbsent 是一种很好的方法,并且比使用标准映射操作更容易读/写.我有一些看起来像这样的代码:

I have been using Java's ConcurrentMap for a map that can be used from multiple threads. The putIfAbsent is a great method and is much easier to read/write than using standard map operations. I have some code that looks like this:

ConcurrentMap<String, Set<X>> map = new ConcurrentHashMap<String, Set<X>>();

// ...

map.putIfAbsent(name, new HashSet<X>());
map.get(name).add(Y);

可读性很好,但它确实需要每次创建一个新的 HashSet,即使它已经在地图中.我可以这样写:

Readability wise this is great but it does require creating a new HashSet every time even if it is already in the map. I could write this:

if (!map.containsKey(name)) {
    map.putIfAbsent(name, new HashSet<X>());
}
map.get(name).add(Y);

通过这种更改,它失去了一些可读性,但不需要每次都创建 HashSet.在这种情况下哪个更好?我倾向于支持第一个,因为它更具可读性.第二个会表现得更好,可能更正确.也许有比这两种方法都更好的方法.

With this change it loses a bit of readability but does not need to create the HashSet every time. Which is better in this case? I tend to side with the first one since it is more readable. The second would perform better and may be more correct. Maybe there is a better way to do this than either of these.

以这种方式使用 putIfAbsent 的最佳做法是什么?

What is the best practice for using a putIfAbsent in this manner?

推荐答案

并发很难.如果您打算使用并发映射而不是直接锁定,那么您不妨尝试一下.确实,不要进行不必要的查找.

Concurrency is hard. If you are going to bother with concurrent maps instead of straightforward locking, you might as well go for it. Indeed, don't do lookups more than necessary.

Set<X> set = map.get(name);
if (set == null) {
    final Set<X> value = new HashSet<X>();
    set = map.putIfAbsent(name, value);
    if (set == null) {
        set = value;
    }
}

(通常的 stackoverflow 免责声明:在我的脑海里.未测试.未编译.等等)

(Usual stackoverflow disclaimer: Off the top of my head. Not tested. Not compiled. Etc.)

更新: 1.8 添加了 computeIfAbsent 默认方法到 ConcurrentMap(和 Map 这有点有趣,因为该实现对于 ConcurrentMap 来说是错误的).(并且 1.7 添加了菱形运算符"<>.)

Update: 1.8 has added computeIfAbsent default method to ConcurrentMap (and Map which is kind of interesting because that implementation would be wrong for ConcurrentMap). (And 1.7 added the "diamond operator" <>.)

Set<X> set = map.computeIfAbsent(name, n -> new HashSet<>());

(注意,您负责ConcurrentMap 中包含的HashSet 的任何操作的线程安全.)

(Note, you are responsible for the thread-safety of any operations of the HashSets contained in the ConcurrentMap.)

这篇关于在使用 ConcurrentMap 的 putIfAbsent 之前,您是否应该检查地图是否包含密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆