我有一个Android应用程序,其核心组件是HashMap<String,float[]>.
系统具有高并发性。例如
以下是我经常出现的三种情况,它们本质上是高度重叠的
我在不同的线程中执行所有这些操作,因此使用ConcurrentHashMap ,因为检索中的某些不一致并不重要。例如在迭代地图时,如果添加了新条目,那么在我确保下次读取它们时不会立即读取这些新值并不重要。
同时删除条目时我每次都在重新创建迭代器以避免“ConcurrentModificationException”
假设有以下hashmap(即ConcurrentHashmap)
ConcurrentHashMap<String,float[]> test=new ConcurrentHashMap<String, float[]>(200);
现在进行检索我执行以下操作
Iterator<String> reader=test.keySet().iterator();
while(reader.hasNext())
{
String s=reader.next();
float[] temp=test.get(s);
//do some operation with float[] temp here(read only operation)
}
并且要删除我执行以下操作
boolean temp = true;
while (temp) {
for (String key : test.keySet()) {
temp = false;
if (key.contains("abc")) {
test.remove(key);
temp = true;
break;
}
}
}
当插入新值时,我只是做
test.put("temp value", new float[10]);
我不确定它是否是一种非常有效的利用方式。同样重要的是不要读取已移除的值(但是我需要效率,并且因为迭代器在函数调用期间再次创建,所以它保证在下次我没有获取删除的值),因此可能存在很大的不一致性耐受?
有人可以告诉我一个有效的方法吗?
PS。我忘了提到为什么我这样做了删除操作。 我现在已经将其删除的条件更改为等于包含(可能有多个蜇具有前缀“abc”后跟不同的后缀。所以我需要删除所有那些。
答案 0 :(得分:4)
遍历散列映射中的所有键并对其值执行某些操作(只读操作)。
不要迭代密钥集,然后检索值 - 直接迭代条目集:
for (Map.Entry<String, float[]> e : map.entrySet() {
String key = e.getKey();
float[] value = e.getValue();
//do something with them
}
一般情况下效率更高(即使是“正常”HashMaps),但它也会减少您的情况下的争用(访问地图的次数减少一半)。
在Hashmap中添加新的键值对。
是的,只是:map.put(s, f);
从Hashmap中删除某些键。
如果你需要检查密钥是否包含给定的子字符串,那么你需要像你一样迭代密钥,尽管我不确定为什么你有一个while + for + break而不是一个简单的for。
答案 1 :(得分:2)
由于您使用ConcurrentHashMap
的方式,您正在精确地删除其Concurrent
特征。您(重新)同步的尝试将非常频繁,但并非总是如此。
您是否考虑将keys
留在HashMap
?我想的是:
public static final float[] DELETED= new float[0] ;
/* delete */
test.put(key,DELETED);
/* insert */
test.put(key,value);
/* iterate */
for(Map.Entry<String,float[]> e: test.entrySet ) {
if( e.getValue() != DELETED ) {
operateOn(e);
}
}
如果键太易变(即一段时间后你会有太多DELETED项),那么你可以创建一个清理Thread
。
答案 2 :(得分:0)
根据ConcurrentHashMap API,它的迭代器永远不会抛出ConcurrentModificationException,所以你不需要在删除后中断。但无论如何,迭代和删除的正确方法是
for (Iterator<String> i = test.keySet().iterator(); i.hasNext();) {
String next = i.next();
if (next.equals("abc")) {
i.remove();
}
}
这样,即使没有ConcurrentModificationException的失败快速迭代器,它也能正常工作