如何迭代(并更改)作为另一个集合的值的集合

时间:2013-01-14 18:28:31

标签: java collections hashmap hashset

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

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。我该怎么做才能在我的地图中迭代并对这个集合进行更改?

2 个答案:

答案 0 :(得分: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
    }
}

答案 1 :(得分:1)

我认为你得到了异常,因为你在迭代期间修改了集合(在未包含在问题中的行中)。如果它们检测到集合的结构已经改变,那么“失败快速”的迭代器就会抛出它。

  

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

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

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