Java のコンテナ マップなど:
for(人 人 : pList){
if(person.getGender()==Gender.MALE){
pList.remove(person); //トラバーサル中に削除操作は実行できません。
}
}
Map を走査するときは、通常、そのキー値の Set を取得し、イテレータを使用して Map を走査します。
走査プロセス中は、Map 内の要素のみを処理できることに注意してください。Map 要素の追加や縮小はできず、例外が発生します (実行中には使用できません)。トラバーサル プロセス)、マップ内の要素を変更、削除、または追加します)。
報告される例外は java.util.ConcurrentModificationException 例外です
パブリック クラス ConcurrentModificationExceptionextends RuntimeException
この例外は、メソッドがオブジェクトの同時変更を検出したが、そのような変更は許可しない場合にスローされます。
たとえば、あるスレッドがコレクションを反復している間、別のスレッドがコレクションを線形に変更することは通常許可されません。このような場合、反復の結果が不明瞭になることがよくあります。一部のイテレータ実装 (JRE によって提供されるすべての汎用コレクション実装を含む) は、この動作が検出された場合にこの例外をスローすることを選択する場合があります。この操作を実行するイテレータは、将来のある時点で任意の不特定の動作を危険にさらすことなく完全に迅速に失敗するため、フェイルファスト イテレータと呼ばれます。
この例外は、オブジェクトが異なるスレッドによって同時に変更されたことを常に示すわけではないことに注意してください。単一のスレッドがオブジェクトのコントラクトに違反する一連のメソッド呼び出しを発行した場合、オブジェクトはこの例外をスローすることがあります。たとえば、フェイルファスト反復子を使用してコレクションを反復処理しているときに、スレッドがコレクションを直接変更すると、反復子はこの例外をスローします。
一般に、非同期の同時変更が発生するかどうかについて厳密な保証を行うことはできないため、反復子のフェイルファスト動作は保証されないことに注意してください。フェイルファスト操作では、ベストエフォートベースで ConcurrentModificationException がスローされます。したがって、このような操作の正確性を向上させるためにこの例外に依存するプログラムを作成するのは間違いです。ConcurrentModificationException はバグを検出するためにのみ使用する必要があります。
フェールファスト イテレータを使用してコレクションまたはマップを反復処理しているときに、コレクション/マップの内容を直接変更しようとすると、単一スレッドで実行している場合でも java.util.ConcurrentModificationException 例外がスローされます。
イテレータは別のスレッドで動作し、ミューテックス ロックを持ちます。イテレータの作成後、元のオブジェクトを指す単一リンクのインデックス テーブルが確立され、元のオブジェクトの数が変化しても、このインデックス テーブルの内容は同期的に変更されないため、インデックス ポインタが後方に移動することはできません。オブジェクトが反復処理されることが判明したため、フェイルファストの原則に従って、Iterator はすぐに java.util.ConcurrentModificationException 例外をスローします。
したがって、Iterator では、動作中に反復オブジェクトを変更することはできません。ただし、Iterator 独自のメソッド Remove() を使用してオブジェクトを削除することはできます。 Iterator.remove() メソッドは、インデックスの一貫性を維持しながら現在の反復オブジェクトを削除します。
興味深いのは、Collection / Map オブジェクトに実際に要素が 1 つしかない場合、ConcurrentModificationException 例外はスローされないことです。これが Javadoc で指摘されている理由です。正確性を保つためにこの例外に依存するプログラムを作成するのは間違いです。ConcurrentModificationException はバグを検出するためにのみ使用する必要があります。