0

我有一个将字节映射到字节集的映射。我想浏览地图并对场景进行更改。

private HashMap<Byte, HashSet<Byte>> table;
...
Iterator<Entry<Byte, HashSet<Byte>>> it = table.entrySet().iterator();
while( it.hasNext() ) {
   Map.Entry<Byte, HashSet<Byte>> pairs = it.next();
   byte node = pairs.getKey();
   HashSet<Byte> hSet = pairs.getValue();
   Iterator<Byte> setIter = hSet.iterator();
   while( setIter.hasNext() ) {
      byte sNode = setIter.next();  // Throws a ConcurrentModificationException
      ...
   }
 }

当我尝试遍历子迭代器时,此代码会引发 ConcurrentModificationException。我应该怎么做才能在我的地图中迭代和更改这个集合?

4

2 回答 2

1

尝试这样的事情:

for(Byte node : table.keySet()) {
   HashSet<Byte> hSet = table.get(node);
   Iterator<Byte> setIter = hSet.iterator();
   while( setIter.hasNext() ) {
      byte sNode = setIter.next(); 
      ...
   }
 }

如果你想修改hSet你最好的方法可能是循环一个副本Set

for(Byte node : table.keySet()) {
    HashSet<Byte> hSet = table.get(node);

    for (Byte sNode : new HashSet<Byte>(hSet)) {
        //do things which modifies the original hSet
    }
}
于 2013-01-14T18:38:13.677 回答
1

我认为您得到了例外,因为您在迭代期间修改了集合(在未包含在问题中的行中)。如果“快速失败”迭代器检测到集合的结构已更改,则它们会抛出它。

请注意,此异常并不总是表示对象已被不同的线程同时修改。如果单个线程发出一系列违反对象约定的方法调用,则该对象可能会抛出此异常。例如,如果线程在使用快速失败迭代器迭代集合时直接修改了集合,则迭代器将抛出此异常。

http://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html

如果您只是在迭代时从集合中删除,则可以使用迭代器的 remove 方法而不是 Set 方法。如果您还想在迭代时添加到集合中,则需要创建集合的副本并对其进行迭代(但这种情况不太可能,您可以在不迭代的情况下添加到集合中......)

于 2013-01-14T18:53:21.020 回答