Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ConcurrentMap.compute用作删除_Java_Collections_Java 8_Java.util.concurrent_Concurrenthashmap - Fatal编程技术网

Java ConcurrentMap.compute用作删除

Java ConcurrentMap.compute用作删除,java,collections,java-8,java.util.concurrent,concurrenthashmap,Java,Collections,Java 8,Java.util.concurrent,Concurrenthashmap,使用Java8,我在Java.util.concurrent.ConcurrentMap接口上实现了一个包装器,特别是remove(objectkey)方法。因为我需要在删除过程中进行更多检查,所以我需要使用 compute(K键,双功能查看ConcurrentMap.compute的默认实现似乎您可以安全地使用未经检查的强制转换,假设您的remappingFunction可以处理对象而不是K类型并返回null public V remove(Object key) { @Suppres

使用Java8,我在
Java.util.concurrent.ConcurrentMap
接口上实现了一个包装器,特别是
remove(objectkey)
方法。因为我需要在删除过程中进行更多检查,所以我需要使用


compute(K键,双功能查看
ConcurrentMap.compute的默认实现
似乎您可以安全地使用未经检查的强制转换,假设您的
remappingFunction
可以处理
对象
而不是
K
类型并返回
null

public V remove(Object key) {
    @SuppressWarnings("unchecked")
    V result = compute((K)key, (k, v) -> {
        if(v == null) return null;
        ...
    });
    ...
}
compute
实现首先使用
get(key)
(它接受任何对象,因此是安全的),并将结果传递给
remappingFunction
。如果键的类型无效,则结果将为
null
,因此
remappingFunction
也应返回
null
。在这种情况下
包含密钥(key)
将被调用,它也接受任何对象,并将为无效对象返回
false
,而
compute
将返回
null


请注意,的行为有很好的文档记录(甚至提供了等效的代码),因此这种实现将来不太可能中断。

请查看是否可以使用Map的forEach方法并将其放入forEach中

map.forEach((k, v) -> 
System.out.println(k + "=" + v));

我想到的第一个想法是使用
containsKey
预先检查map是否可以处理特定的键对象。如果此方法返回
true
,map可以处理它,因此对
K
进行未选中的强制转换就可以了

但是

ConcurrentMap<String,Integer> map=new ConcurrentSkipListMap<>();
map.put("foo", 42);
map.containsKey(0);
但是,除了线性搜索的性能外,理论上,如果在遍历过程中同时插入同一个密钥,则可能会多次删除密钥


因此,原子安全和类型安全的唯一解决方案是求助于运行时类型令牌(即通常通过类文本初始化):


要自动删除映射,如果存在并且
检查
成功,但不能使用它返回删除是否实际发生,因为
compute…
方法对不存在的键和在这两种情况下删除的键没有区别,将返回
null

“我甚至不能做运行时检查,比如if(key instanceof K)。。。",您可以,但您必须将
存储为包装器实例中的类型令牌。您可以安全地强制转换,因为擦除会剥离类型信息,映射只使用键的
对象
方法。这是一种丑陋但安全且可接受的做法。
ConcurrentMap.compute
只是默认实现,优化了c集合很可能直接实现,而不调用get等。ClassCastException(我自己还没有测试过)是ConcurrentSkipListMap的一个bug,因为它不遵守其约定。如果key不是key类型的实例,则返回false通常会破坏约定,因为这不考虑类型,只需
equals()
results.:“抛出:
ClassCastException
-如果该键的类型不适合此映射()”
ConcurrentMap
不会修改此合同。如果基于类型的预检查不能解决您的问题,则根本没有类型安全解决方案。当然,您可能会发现
ClassCastException
…是的,在文档中没有发现此部分。谢谢,尽管所需的解决方案似乎不存在。
ConcurrentMap<String,Integer> map=new ConcurrentSkipListMap<>();
map.put("foo", 42);
map.containsKey(0);
return map.entrySet().removeIf(e ->
    Objects.equals(key, e.getKey()) && check(e.getKey(), e.getValue()));
ConcurrentMap<K, V> map;
Class<K> keyType;

public boolean remove(Object key) {
    if(!keyType.isInstance(key)) return false;
    K k=keyType.cast(key);
    for(;;) {
        V v=map.get(k);
        if(v==null || !check(k,v)) return false;
        if(map.remove(k, v)) return true;
    }
}
if(keyType.isInstance(key))
    map.computeIfPresent(keyType.cast(key), (k,v) -> check(k, v)? null: v);