java – 用作remove的ConcurrentMap.compute


Java 8中,我在java.util.concurrent.ConcurrentMap接口上实现了一个包装器,特别是remove(Object key)方法.由于我需要在删除期间进行更多检查,因此我需要使用实现该功能

compute(K key,BiFunction<?super K,?super V,?extends V> remappingFunction)

但是,这里的问题是:我必须接受Object但是将其传递给计算为K.使用泛型,我甚至不能像if(key instanceof K)那样进行运行时检查……

我明白为什么计算的签名是这样选择的;如果它只是Object,如果计算需要创建一个新条目,它就不能简单地使用密钥.但我不知道如何解决这个问题 – 是否有任何推荐的模式,但如下所示使用多个调用?

for (;;) {
    V v = map.get();
    if (check(k, v)) {
        if (map.remove(k, v)) return true;
    } else return false;
}

谢谢

最佳答案 看一下ConcurrentMap.compute的默认实现,似乎你可以安全地使用未经检查的强制转换,假设你的remappingFunction可以处理不是K类型的Object并返回null.所以你可以使用:

public V remove(Object key) {
    @SuppressWarnings("unchecked")
    V result = compute((K)key, (k, v) -> {
        if(v == null) return null;
        ...
    });
    ...
}

计算实现首先使用get(key)(它接受任何对象,因此它是安全的),并将结果传递给remappingFunction.如果键具有无效类型,则结果将为null,因此您的remappingFunction也应返回null.在这种情况下,将调用containsKey(key),它也接受任何对象,并且对于无效对象将返回false,并且compute将返回null.

请注意,ConcurretMap.compute的行为已有详细记录(即使提供了等效的代码),因此将来不太可能破坏此类实现.

点赞