如何从ConcurrentHashMap<String, Set<String>>中移除用作值的Set?

How to remove Set, which is used as value, from ConcurrentHashMap<String, Set<String>>?

让我们考虑以下代码:

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<String, Set<String>> 地图,其中地图的 keyStringvalueConcurrentHashSet
  2. 我需要删除 set,这是 map 的值,当 setempty
  3. 由于竞争条件错误,我无法实现 set 的简单删除。

我的问题有什么好的解决办法吗?

如果映射器 returns null

computeIfPresent 删除条目。如果要删除条目,请从映射器中 return null 而不是在单独的步骤中执行删除。

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