ConcurrentMap.compute 用作删除

Rad*_*nsa 5 java collections concurrenthashmap java.util.concurrent java-8

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

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

然而,这里的问题是:我必须接受Object但将其传递给computeas K。对于泛型,我什至无法进行运行时检查,例如if (key instanceof K) ...

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

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

谢谢

Tag*_*eev 1

看看ConcurrentMap.compute它的默认实现,假设您可以remappingFunction处理Objectnot of typeK并 return ,您似乎可以安全地使用未经检查的强制转换null。所以你可以使用:

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

实现compute首先使用get(key)(它接受任何对象,因此它是安全的),并将结果传递给remappingFunction. 如果键的类型无效,那么结果将是null,所以你remappingFunction也应该返回null。在这种情况下,containsKey(key)将调用 will ,它也接受任何对象,并将返回false无效对象并compute返回null

请注意, 的行为ConcurretMap.compute有详细记录(甚至提供了等效代码),因此此类实现将来不太可能中断。