今日javaに会いました.util.C o n c u r r e ntModificationException異常


今日バグを変更します.mapをループし、削除操作があります.コードは次のとおりです.

Iterator<ListItem> iter = ItemMap.keySet.iterator();
while(iter.hasNext()){
ListItem it = iter.next();
//...      
ItemMap.remove(it);
}

結果:

Iterator<ListItem> iter = ItemMap.keySet.iterator();
while(iter.hasNext()){
ListItem it = iter.next();
//...      
iter.remove(it);
}

結果は正しい.
この问题は以前出会ったことがあって、しかし直した后に原因を分析していないで、今日ネット上で见て、とても多く解釈して、回転して来て、検索するために、ほほほ.
もともとMapやCollectionでは、そのAPIでコレクションの内容を直接変更しないでください(java.util.C o n c u r r e ntModificationException異常が発生します)、Iteratorのremove()メソッドを変更する必要があります.
回転---
参照
原因分析:
fail-fast iteratorを使用するCollectionまたはMapの反復操作中にCollection/Mapの内容を直接変更しようとすると、単一スレッドで実行するもjava.util.ConcurrentModificationException異常も放出されます.
Iteratorは独立したスレッドで動作し、mutexロックを持っています.Iteratorが作成すると元のオブジェクトを指す単一チェーンインデックステーブルが作成され、元のオブジェクトの数が変化するとこのインデックステーブルの内容は同期して変化しないため、インデックスポインタが後ろに移動すると反復するオブジェクトが見つからないためfail-fastの原則に従ってIteratorはすぐにjavaを投げ出す.util.ConcurrentModificationException異常.
したがって、Iteratorは作業中に反復されたオブジェクトを変更することは許されません.ただし、Iterator自体のメソッドremove()を使用してオブジェクトを削除することができます.remove()メソッドは、現在の反復オブジェクトを削除しながらインデックスの一貫性を維持します.
興味深いことに、Collection/Mapオブジェクトに実際に要素が1つしかない場合、C o n c u r r r e ntModificationException異常は放出されません.つまりjavadocでは、it would be wrong to write a program that depended on this exception for its correctness:C o n c u r e ntModificationException should be used only to detect bugs.
添付:ibm developerworksからjava.util.concurrentパッケージの説明クリップ:
      java.utilパッケージのコレクションクラスはfail-fast反復器を返します.これは、スレッドがコレクションコンテンツで反復されると、コレクションがそのコンテンツを変更しないと仮定します.fail-fast反復器が反復中に変更操作が行われたことを検出すると、制御不能な例外であるC o n c u r r r e ntModificationExceptionが放出されます.
反復中にコレクションを変更しない必要性は、通常、多くの同時アプリケーションに不便をもたらします.逆に、反復器が合理的に操作する限りjavaのような集合の一貫したビューを提供できることを保証するために、同時修正を可能にすることが好ましい.util.concurrent集合クラスの反復器が行ったように.
     java.util.concurrent集合が返す反復器を弱一致反復器と呼ぶ.これらのクラスでは、要素が反復から削除され、next()メソッドによって返されていない場合、呼び出し元には戻りません.要素が反復から追加されている場合は、呼び出し元を返すか、返さないかのいずれかです.1回の反復では、最下位のセットを変更しても、要素は2回返されません.