5

可能的重复:
Java:高效等效于在迭代集合时
移除

我正在尝试循环HashMap

Map<String, Integer> group0 = new HashMap<String, Integer>();

...并提取group0. 这是我的方法:

// iterate through all Members in group 0 that have not been assigned yet
for (Map.Entry<String, Integer> entry : group0.entrySet()) {

    // determine where to assign 'entry'
    iEntryGroup = hasBeenAccusedByGroup(entry.getKey());
    if (iEntryGroup == 1) {
        assign(entry.getKey(), entry.getValue(), 2);
    } else {
        assign(entry.getKey(), entry.getValue(), 1);
    }
}

这里的问题是每次调用assign()都会从中删除元素group0,从而修改其大小,从而导致以下错误:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
    at java.util.HashMap$EntryIterator.next(HashMap.java:834)
    at java.util.HashMap$EntryIterator.next(HashMap.java:832)
    at liarliar$Bipartite.bipartition(liarliar.java:463)
    at liarliar$Bipartite.readFile(liarliar.java:216)
    at liarliar.main(liarliar.java:483)

那么......我如何在group0动态变化时循环遍历元素?

4

6 回答 6

7

其他人已经提到了正确的解决方案,但没有真正说明它。所以这里是:

Iterator<Map.Entry<String, Integer>> iterator = 
    group0.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<String, Integer> entry = iterator.next();

    // determine where to assign 'entry'
    iEntryGroup = hasBeenAccusedByGroup(entry.getKey());

    if (iEntryGroup == 1) {
        assign(entry.getKey(), entry.getValue(), 2);
    } else {
        assign(entry.getKey(), entry.getValue(), 1);
    }

    // I don't know under which conditions you want to remove the entry
    // but here's how you do it
    iterator.remove();
}

此外,如果您想在分配函数中安全地更改映射,则需要传入迭代器(您只能使用删除函数并且只能使用一次)或条目来更改值。

于 2010-08-19T05:57:06.363 回答
3

正如我在这里的回答所说:

遍历集合,在循环中删除时避免 ConcurrentModificationException

使用 Iterator.remove()

于 2010-08-19T00:38:18.133 回答
1

在您的特定情况下,我不会修改 HashMap 的结构,而只是将要删除的值设为空。然后,如果您最终访问空值,请跳过它。

在一般情况下,我更喜欢使用 Stack 来处理这样的事情,因为它们特别容易可视化,所以我倾向于较少遇到边界条件问题(只是保持弹出直到为空)。

于 2010-08-19T02:10:55.700 回答
1

您可以使用ConcurrentHashMap

于 2010-08-19T01:39:09.893 回答
0

如果要在循环遍历集合时修改集合,则需要使用实际的迭代器及其 remove 方法。使用 foreach 构造实际上没有任何方法可以做到这一点。

如果您尝试在一次迭代中删除多个条目,则需要遍历不受地图支持的内容。

Set<String> keys = new HashSet<String>(group0.keySet());
for (String key : keys) {
  if (group0.containsKey(key)) {
    Integer value = group0.get(key);
    //your stuff 
  }
}
于 2010-08-19T00:02:55.280 回答
0

在这种情况下,如何assign修改group0?需要更多细节。通常,您无法在迭代集合时对其进行修改。您通过Iterator接口进行修改。

于 2010-08-19T00:32:25.497 回答