25

for-eachループを使用してコレクションを反復処理しながらコレクションを変更すると、が得られConcurrentModificationExceptionます。回避策はありますか?

4

4 に答える 4

42

を使用しIterator#removeます。

これは、反復中にコレクションを変更する唯一の安全な方法です。詳細については、コレクションインターフェイスのチュートリアルを参照してください。

反復中に要素を追加する機能も必要な場合は、を使用してListIteratorください。

于 2011-08-05T15:08:42.783 に答える
13

回避策の 1 つは、変更を保存し、ループ後に追加/削除することです。

例えば:

List<Item> toRemove = new LinkedList<Item>();

for(Item it:items){
    if(remove){
        toRemove.add(it);
    }
}
items.removeAll(toRemove);
于 2011-08-05T15:11:25.093 に答える
3

2 番目の回避策は、反復子が例外を発生させないコレクション クラスを使用することです。たとえばConcurrentLinkedQueueConcurrentHashMapなどです。

これらは、反復子の一貫性のより弱いモデルを提供することにより、例外をスローする必要を回避します。(もちろん、これらのモデルを理解し、アプリケーションに適しているかどうかを判断する必要があります。)

通常、これらは非同時コレクションよりも少し遅くなりますが、大きな競合がある場合は、同期コレクション ラッパーよりも高速です。

于 2011-08-05T15:14:50.497 に答える
2

コレクションから要素を削除するだけの場合は、Iterable の代わりに Iterator を使用できます。

それ以外の場合、元のコレクションを反復するのではなく、最初にリストのコピーを作成することができます。たとえば、コレクションがリストの場合、新しい ArrayList(originaList) を作成してそれを反復処理できます。変更は元のリストに対して行う必要があります。

ユースケースに適した別の方法は、 for-each ではなく従来の for- を使用することです。

于 2011-08-05T15:11:56.263 に答える