を使用すればIterator.remove()
、すべて問題ありません。を使用するArryaList.remove()
と、常にエラーが表示されますjava.util.ConcurrentModificationException
。
誰でも理由を指摘できますか?
を使用すればIterator.remove()
、すべて問題ありません。を使用するArryaList.remove()
と、常にエラーが表示されますjava.util.ConcurrentModificationException
。
誰でも理由を指摘できますか?
javadocs はそれをすべて言います:
この例外は、そのような変更が許可されていない場合に、オブジェクトの同時変更を検出したメソッドによってスローされる場合があります。
たとえば、別のスレッドが Collection を反復処理しているときに、その Collection を変更することは一般的に許可されていません。一般に、反復の結果は、これらの状況では未定義です。一部の Iterator 実装 (JRE によって提供されるすべての汎用コレクション実装の実装を含む) は、この動作が検出された場合に、この例外をスローすることを選択する場合があります。これを行う反復子は、将来の不確定な時点で恣意的で非決定論的な動作を危険にさらすのではなく、迅速かつ明確に失敗するため、フェイルファスト反復子として知られています。
コレクションを変更し、同時にそれを反復しています。
基本的に、それが機能するように設計されているためです。リストから要素を削除すると、反復子はそれを認識せず、リスト内の別の要素にアクセスしようとすると、リストが変更され、エラーが発生します。しかし、反復子を介して要素を削除すると、反復子は削除を認識し、そのデータ構造を適切に調整して続行します。
まさにドキュメントから
この例外は、そのような変更が許可されていない場合に、オブジェクトの同時変更を検出したメソッドによってスローされる場合があります。
たとえば、別のスレッドが Collection を反復処理しているときに、その Collection を変更することは一般的に許可されていません。一般に、反復の結果は、これらの状況では未定義です。一部の Iterator 実装 (JRE によって提供されるすべての汎用コレクション実装の実装を含む) は、この動作が検出された場合に、この例外をスローすることを選択する場合があります。これを行う反復子は、将来の不確定な時点で恣意的で非決定論的な動作を危険にさらすのではなく、迅速かつ明確に失敗するため、フェイルファスト反復子として知られています。
リストを繰り返し処理しているときに要素を削除する必要がある場合は、常に iterator を使用する必要があります。
例えば
List<String> list = //...
//...
Iterator<String> iter = list.iterator();
while(iter.hasNext()) {
String str = itr.next();
//...
if(/* ... */) {
iter.remove(str);
}
}
これは、リストを繰り返し処理しているときにリストから要素を削除する最も安全な方法です。
注: 次のようなことを行うべきではありません。
List<String> list = //...
//...
for(String str : list) {
if(/* ... */) {
list.remove(); // <-- should not do this
}
}
ほとんどの場合、ConcurrentModificationException
. その強化された for ループは、フードの下でイテレータを使用します。また、イテレータを使用する代わりに、リストから要素を手動で削除しています。そのため、その例外が発生します。