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

反復中にセットを変更したため(質問に含まれていなかった行で)、例外が発生したと思います。コレクションの構造が変更されたことを検出した場合、「フェイルファスト」反復子はそれをスローします。

この例外は、オブジェクトが別のスレッドによって同時に変更されたことを常に示すわけではないことに注意してください。1 つのスレッドが、オブジェクトのコントラクトに違反する一連のメソッド呼び出しを発行すると、オブジェクトはこの例外をスローする可能性があります。たとえば、フェイルファスト反復子を使用してコレクションを反復処理しているときに、スレッドがコレクションを直接変更すると、反復子はこの例外をスローします。

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

反復中にセットから削除するだけの場合は、Set メソッドの代わりに反復子の remove メソッドを使用できます。反復中にセットにも追加する場合は、セットのコピーを作成し、それを反復する必要があります (ただし、このケースはほとんどありません。反復せずにセットに追加できます...)

于 2013-01-14T18:53:21.020 に答える