我想使用番石榴来制作具有以下属性的地图:
读很多,但是写很少。
数据不会过期。
必须同步,因此写入是“原子的”并且多次读取不会相互干扰。
该地图应使用MapConstraint
API,其中一些MapConstraint
与地图本身的内容背道而驰(通常,如果记录或其他记录存在,请勿覆盖它:改为抛出IllegalStateException
)。我看到MapConstraint
界面不会给Map
带来约束。MapConstraint
的检查必须在同步部分内部进行。
我已经考虑过使用ReadWriteLock
了,但是我想知道MapMaker
是否可以在这里为我提供帮助,因为我对该API不太熟悉。
那我有什么选择呢?
编辑:我的目标不是一个简单的putIfAbsent
:我需要在插入值之前对映射执行多次检查,始终在同步写入中进行。
最佳答案
我不确定您是否可以使用MapConstraint语义轻松地做到这一点。您可以通过在构造过程中向其传递对地图的引用来使MapConstraint知道底层地图:
MapConstraints.constrainedMap(map, new MyCustomMapConstraint(map));
但这将是丑陋的/冒险的。有人可能会错误地这样做:
MapConstraint constraint = new MyCustomMapConstraint(firstMap);
Map constrainedMap = MapConstraints.constrainedMap(secondMap, constraint);
另外,它不能解决同步问题。
如果要这样做,我将使用ConcurrentMap提供的“ putIfAbsent”方法。我将使用ForwardingConcurrentMap创建一个ConcurrentMap包装器:
public class ProtectionistMap<K, V> extends ForwardingConcurrentMap<K, V> {
private final ConcurrentMap<K, V> delegate;
public ProtectionistMap(ConcurrentMap<K, V> delegate) {
this.delegate = checkNotNull(delegate);
}
@Override
protected ConcurrentMap<K, V> delegate() {
return delegate;
}
@Override
public V put(K key, V value) {
V result = putIfAbsent(key, value);
// The second part of the test is necessary when a map may contain null values...
if (result != null || value == null && containsKey(key)) {
throw new IllegalArgumentException("Map already had an entry for key " + key);
}
return result;
}
@Override
public void putAll(Map<? extends K, ? extends V> map) {
standardPutAll(map);
}
}
关于java - 在某种程度上同步的 map 上使用 Guava 的MapConstraint,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4922521/