2013-06-24 20 views
72

リストをループしている間、条件に応じてリストのアイテムを削除したいと思います。以下のコードを参照してください。リストからアイテムを削除する

これは私にConcurrentModificationの例外を与えます。

for (Object a : list) { 
    if (a.getXXX().equalsIgnoreCase("AAA")) { 
     logger.info("this is AAA........should be removed from the list "); 
     list.remove(a); 
    } 
} 

どのようにすることができますか?

+2

OHWは、また、あなたは、これらの静的な輸入を必要とします。その代わりにコピーを作成してアイテムを削除するか、イテレータに直接コピーしてください。 – thegrinner

答えて

55

Iteratorを使用し、forループの代わりにiteratorremove()を呼び出す必要があります。

3
//first find out the removed ones 

List removedList = new ArrayList(); 
for(Object a: list){ 
    if(a.getXXX().equalsIgnoreCase("AAA")){ 
     logger.info("this is AAA........should be removed from the list "); 
     removedList.add(a); 

    } 
} 

list.removeAll(removedList); 
+3

なぜそんなに複雑な... – m0skit0

+4

それは複雑ではありません。あるリストを別のリストから削除する別の方法。 – Makky

+3

新しいオブジェクトを作成する必要がないときや、おそらくリストを2回ループしているときに作成します。 – m0skit0

13

リストの反復処理中にリストを変更することはできません。削除するオブジェクトを一時的に保存することでこれを解決できます。

List<Object> toRemove = new ArrayList<Object>(); 
for(Object a: list){ 
    if(a.getXXX().equalsIgnoreCase("AAA")){ 
     toRemove.add(a); 
    } 
} 
list.removeAll(toRemove); 
+0

リストの反復処理中にリストを変更することはできません。 –

+2

@AlexVentura iteratorパターンがどのように機能するかが原因です。イテレータが参照していないリスト(特にサイズ)をイテレータが参照する場合、イテレータは「混乱」します。 –

22

既にループしているため、実行できません。

INORDERこの状況が安全に、リストから要素を削除することができguarenteesイテレータ、...リストが文字列であることを、追加の前提を作る

List<Object> objs; 
Iterator<Object> i = objs.iterator(); 
while (i.hasNext()) { 
    Object o = i.next(); 
    //some condition 
    i.remove(); 
} 
155
for (Iterator<String> iter = list.listIterator(); iter.hasNext();) { 
    String a = iter.next(); 
    if (...) { 
     iter.remove(); 
    } 
} 

を使用しないようにします。 既に回答済みのとおり、list.iterator()が必要です。 listIteratorでも少しの操作が可能です。

5

ここで提供される優れたソリューションの他に、私は別のソリューションを提供したいと考えています。

依存関係を自由に追加できるかどうかはわかりませんが、可能であればhttps://code.google.com/p/guava-libraries/を依存関係として追加することができます。このライブラリは、多くの基本的な機能操作のサポートをJavaに追加し、コレクションをより簡単で読みやすくすることができます。

コードでは、あなたのリストに入力されたものがわからないので、私はリストの型をTで置き換えました。

この問題はグアバと次のように解決することができます:

List<T> filteredList = new Arraylist<>(filter(list, not(XXX_EQUAL_TO_AAA))); 

そしてどこかにあなたがようXXX_EQUAL_TO_AAAを定義します。しかし、これはおそらくあなたの状況では過剰です

public static final Predicate<T> XXX_EQUAL_TO_AAA = new Predicate<T>() { 
    @Override 
    public boolean apply(T input) { 
     return input.getXXX().equalsIgnoreCase("AAA"); 
    } 
} 

。これは、コレクションを扱うほど強力なものになります。あなたが反復処理している間は、リストとリストから要素を削除することはできません

import static com.google.common.base.Predicates.not; 
import static com.google.common.collect.Collections2.filter; 
関連する問題