【问题标题】:How to remove Set, which is used as value, from ConcurrentHashMap<String, Set<String>>?如何从 ConcurrentHashMap<String, Set<String>> 中删除用作值的 Set?
【发布时间】:2019-03-03 20:05:28
【问题描述】:

让我们考虑以下代码:

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

// Add element: {mapKey, setValue}

map.computeIfAbsent(mapKey, new Function<String, Set<String>>() {
    @Override
    public Set<String> apply(String mapK) {
        return ConcurrentHashMap.newKeySet();
    }
}).add(setValue);

// Remove element: {mapKey, setValue}

Set<String> updatedSet = map.computeIfPresent(mapKey, new BiFunction<String, Set<String>, Set<String>>() {
    @Override
    public Set<String> apply(String mapK, Set<String> old) {
        old.remove(setValue);
        return old;
    }
});

// I need remove mapKey, but I cannod do this like this, because of race condition bug
if (updatedSet.isEmpty()) {
    map.remove(mapKey);
}

所以,我们可以看到:

  1. 我们有ConcurrentHashMap&lt;String, Set&lt;String&gt;&gt; 映射,其中映射的keyStringvalueConcurrentHashSet
  2. setempty 时,我需要删除set,这是map 的值。
  3. 由于竞争条件错误,我无法实现对 set 的天真删除。

我的问题有什么绝妙的解决方案吗?

【问题讨论】:

  • @dnault 谢谢。
  • 附带说明,由于您显然使用的是 Java 8,因此您可以对这些函数使用 lambda 表达式。
  • @Holger 是的,谢谢。我想,这段代码更明显。

标签: java concurrency race-condition java.util.concurrent concurrenthashmap


【解决方案1】:

如果映射器返回nullcomputeIfPresent 将删除该条目。如果要删除条目,请从映射器返回 null,而不是在单独的步骤中执行删除。

(另外,你真的应该将.add(setValue) 折叠到你的computeIfAbsent 映射器中,并使用compute 而不是computeIfAbsent,因为你现在没有做任何事情来保护add 调用。使用merge 也是一种选择。)

【讨论】:

    猜你喜欢
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-31
    • 1970-01-01
    • 2015-10-21
    • 2019-08-26
    • 1970-01-01
    相关资源
    最近更新 更多