ConcurrentModificationException
イテレーション中にコレクションが変更された場合に発生するJavaの例外
概要
ConcurrentModificationExceptionは、コレクションのイテレーション中にそのコレクションの構造が変更された場合に発生します。シングルスレッドでもfor-eachループ内での要素追加・削除で頻繁に発生します。
エラーメッセージ
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
at com.example.MyClass.process(MyClass.java:25)
原因
- for-eachループ内での要素削除: 拡張forループの反復中に
remove()やadd()を呼び出している - マルチスレッドでの同時アクセス: 一方のスレッドがイテレーション中に、別スレッドがコレクションを変更している
- Stream処理中のソース変更: Streamのソースとなるコレクションを処理中に変更している
解決策
1. Iterator.remove()を使用する
イテレーション中の削除にはIteratorのremove()メソッドを使う。
| |
2. removeIf()を使用する(Java 8以降)
条件に一致する要素を安全に削除できる。
| |
3. ConcurrentHashMapを使用する
マルチスレッド環境ではスレッドセーフなコレクションを使う。
| |
4. CopyOnWriteArrayListを使用する
読み取りが多く書き込みが少ない場合に有効。
| |
5. 新しいリストを作成する
削除対象を収集してから一括で処理する。
| |
関連エラー
- NullPointerException - null参照アクセスで発生
- StackOverflowError - 無限再帰等で発生
Java の他のエラー
この記事は役に立ちましたか?