使用Guava,我希望有一个具有以下属性的地图:
MapConstraint
API,其中一些MapConstraint
是针对地图本身的内容(通常如果记录或其他内容存在,请不要覆盖它:抛出{{{ 1}}而不是)。我看到IllegalStateException
界面未对MapConstraint
进行约束。Map
的检查必须在同步部分内完成。我已经考虑过使用MapConstraint
,但我想知道ReadWriteLock
是否可以帮助我,因为我对这个API不是很熟悉。
那么我的选择是什么?
编辑:我的目标不是一个简单的MapMaker
:我需要在插入值之前对地图执行几次检查,总是在同步写入中。
答案 0 :(得分:1)
我不确定您是否可以使用 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);
}
}
答案 1 :(得分:0)
我的回答根本不是关于番石榴,但为什么不考虑使用java.util.concurrent.ConcurrentHashMap?除了直接支持MapConstraint之外,它还拥有您所需要的一切。
如果存在记录,则可以使用containsKey()方法,而不是抛出异常。 或者,如果您需要异常,只需创建自己继承自ConcurrentHashMap的类。如果你真的需要它,它也可以使用MapConstraint。 看起来像2分钟的工作,代码将如下所示:
public V put(K key, V value) {
if (value == null)
throw new NullPointerException();
int hash = hash(key.hashCode());
Segment seg = segmentFor(hash);
V result;
seg.lock()
try {
constraint.checkKeyValue(key, value);
v = seg.put(key, hash, value, false)
} finally {
seg.unlock()
}
return result;
}
不要从字面上理解这个代码,这只是一个例子;)
如果您需要有关ConcurrentHashMap内部的更多信息,可以在这里查看: ConcurrentHashMap revealed