使用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);
}
答案 0 :(得分:3)
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();
}
}
答案 1 :(得分:1)
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
)通常不会阻止,因此可能与更新操作重叠(包括put
和remove
)。检索反映了最近已完成更新操作的结果。对于putAll
和clear
等聚合操作,并发检索可能反映仅插入或删除某些条目。类似地,Iterators和Enumerations在迭代器/枚举的创建时或之后的某个时刻返回反映哈希表状态的元素。他们不抛出ConcurrentModificationException
。但是,迭代器被设计为一次只能由一个线程使用。
答案 2 :(得分:0)
您可以在entrySet上直接使用removeIf:
map.entrySet().removeIf( entry -> .. some condicion on entry )
请注意,Java 8中有一个 bug ,仅在Java 9中已已修复(here)。