Java从ConcurrentHashMap中删除特定项

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java从ConcurrentHashMap中删除特定项相关的知识,希望对你有一定的参考价值。

使用remove()方法好吗?我读过一篇文章,说明同步还没有添加到remove方法中。如何从ConcurrentHashMap中正确删除特定项?

示例代码:

    ConcurrentHashMap<String,Integer> storage = new ConcurrentHashMap<String,Integer>();
    storage.put("First", 1);
    storage.put("Second", 2);
    storage.put("Third",3);


    //Is this the proper way of removing a specific item from a tread-safe collection?
    storage.remove("First");

    for (Entry<String, Integer> entry : storage.entrySet()) {
        String key = entry.getKey();
        Object value = entry.getValue();
        // ...
        System.out.println(key + " " + value);
    }
答案

remove方法确实在锁上同步。确实检查了ConcurrentHashMap#remove()的代码,有一个调用lock方法来获取锁:

public V remove(Object key) {
    int hash = hash(key.hashCode());
    return segmentFor(hash).remove(key, hash, null);
}

其中ConcurrentHashMap.Segment#remove(key, hash, null)定义为:

V remove(Object key, int hash, Object value) {
     lock();
     try {
        ...

请注意Javadoc描述:

检索操作(包括get)通常不会阻塞,因此可能与更新操作(包括putremove)重叠。检索反映了最近完成的更新操作的结果。对于诸如putAllclear之类的聚合操作,并发检索可能反映仅插入或删除某些条目。类似地,Iterators和Enumerations在迭代器/枚举的创建时或之后的某个时刻返回反映哈希表状态的元素。他们不扔ConcurrentModificationException。但是,迭代器设计为一次只能由一个线程使用。

另一答案

一个Iterator应该做的工作:

Iterator<Map.Entry<String, Integer>> iterator = storage.entrySet().iterator();
while(iterator.hasNext())
{
    Map.Entry<String, Integer> entry = iterator.next();
    if(entry.getKey().equals("First"))
    {
       iterator.remove();
    }
 }

参考:https://dzone.com/articles/removing-entries-hashmap

另一答案

您可以直接在entrySet上使用removeIf:

map.entrySet().removeIf( entry -> .. some condicion on entry ) 

请注意,Java 8中存在一个仅从Java 9(here)修复的错误。

以上是关于Java从ConcurrentHashMap中删除特定项的主要内容,如果未能解决你的问题,请参考以下文章

死磕 java集合之ConcurrentHashMap源码分析

死磕 java集合之ConcurrentHashMap源码分析

ConcurrentHashMap 中 entrySet().removeIf 的行为

Java集合--ConcurrentHashMap原理

Java集合——ConcurrentHashMap

java中的ConcurrentHashMap