web-dev-qa-db-ja.com

java.util.ConcurrentModificationException Android配列リストから要素を削除した後

Androidアプリに次のコードがあります:

/**
 * callback executed after fetching the data.
 */
public void OnPointsFetch(ArrayList<Shop> result) {

    toggleLoader(false);

    this.shops = result;

    if(activeFilter == Constants.POINTS_FILTER_AVAILABLE){
        for(Shop s : result){
            if(s.getClientPoints().getPointsAvailable() == 0){
                this.shops.remove(s);
            }
        }
    }
    else{
        for(Shop s : result){
            if(s.getClientPoints().getPointsSpent() == 0){
                this.shops.remove(s);
            }   
        }
    }


    ptsListAdapter.setCollection(this.shops);
    ptsListAdapter.setFilter(this.activeFilter);

}

このメソッドは、非同期タスクの結果で呼び出されます。リストアダプタに渡す前に、コレクションのいくつかの要素を削除する必要があります。

    11-23 17:39:59.760: E/AndroidRuntime(19777): Java.util.ConcurrentModificationException
11-23 17:39:59.760: E/AndroidRuntime(19777):    at Java.util.ArrayList$ArrayListIterator.next(ArrayList.Java:569)
17
brpaz

リストを繰り返し処理している間は、リストからアイテムを削除することはできません。イテレータとそのremoveメソッドを使用する必要があります。

for(Iterator<Shop> it = result.iterator(); it.hasNext();) {
    Shop s = it.next();
    if(s.getClientPoints().getPointsSpent() == 0) {
        it.remove();
    }   
}
47
assylias

通常、このエラーが発生するのは

  1. コレクションを反復処理しているときに、コレクションを直接変更します

    またはさらに悪い場合

  2. 1つのスレッドがコレクションを変更し、別のスレッドがコレクションを反復処理します。

1
AlexWien

内部的には同じリストを再度変更しようとしているため、受け入れられた回答が機能するかどうかはわかりません。よりクリーンなアプローチは、「削除」リストを維持し、ループ内でそのリストに要素を追加し続けることです。削除リストの準備ができたら、ループの後で削除できます。これは、削除された要素を再処理する必要がないすべての場合に機能するはずです。はいの場合、既存の削除リストでその要素の存在を確認できます。

    List<String> list = new ArrayList<String>();
    List<String> listRemove = new ArrayList<String>();

    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");
    list.add("6");
    list.add("7");
    list.add("8");

    System.out.println("list : " + list);

    for (String i : list) {
        if (i.equals("2")) {
            listRemove.add(i);
        }
    }
    list.removeAll(listRemove);
    System.out.println("updated list: " + list);
1
dotrc