java - 如何从 ConcurrentHashMap 中删除用作值的 Set>?
问题描述
让我们考虑以下代码:
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);
}
所以,我们可以看到:
- 我们有
ConcurrentHashMap<String, Set<String>>
地图,key
地图的位置是String
,并且value
是ConcurrentHashSet
。 - 我需要删除
set
, 这是map
, whenset
is的值empty
。 set
由于竞争条件错误,我无法实现天真的删除。
我的问题有什么绝妙的解决方案吗?
解决方案
computeIfPresent
如果映射器返回,则删除条目null
。null
如果要删除条目,请从映射器返回,而不是在单独的步骤中执行删除。
(此外,您应该真正将 折叠.add(setValue)
到您的computeIfAbsent
映射器中,并使用compute
而不是computeIfAbsent
,因为您现在没有做任何事情来保护add
呼叫。使用merge
也是一种选择。)