web-dev-qa-db-ja.com

ArrayListのConcurrentModificationException

私は次のコードを持っています:

private String toString(List<DrugStrength> aDrugStrengthList) {
    StringBuilder str = new StringBuilder();
        for (DrugStrength aDrugStrength : aDrugStrengthList) {
            if (!aDrugStrength.isValidDrugDescription()) {
                aDrugStrengthList.remove(aDrugStrength);
            }
        }
        str.append(aDrugStrengthList);
        if (str.indexOf("]") != -1) {
            str.insert(str.lastIndexOf("]"), "\n          " );
        }
    return str.toString();
}

コードを実行しようとすると、ConcurrentModificationExceptionが返されます。コードが同じスレッドで実行されている場合でも、その理由を説明できる人はいますか?そして、どうすればそれを回避できますか?

77
mabuzer

「for each」ループでブラウズしている場合、リストから削除することはできません。 Iteratorを使用できます。交換:

for (DrugStrength aDrugStrength : aDrugStrengthList) {
    if (!aDrugStrength.isValidDrugDescription()) {
        aDrugStrengthList.remove(aDrugStrength);
    }
}

と:

for (Iterator<DrugStrength> it = aDrugStrengthList.iterator(); it.hasNext(); ) {
    DrugStrength aDrugStrength = it.next();
    if (!aDrugStrength.isValidDrugDescription()) {
        it.remove();
    }
}
157
Konrad Garus

他の答えが言うように、繰り返し処理しているコレクションからアイテムを削除することはできません。これを回避するには、明示的にIteratorを使用し、そこからアイテムを削除します。

Iterator<Item> iter = list.iterator();
while(iter.hasNext()) {
  Item blah = iter.next();
  if(...) {
    iter.remove(); // Removes the 'current' item
  }
}
24
Edward Dale

私は次のようなループの逆順が好きです:

int size = list.size();
for (int i = size - 1; i >= 0; i--) {
    if(remove){
        list.remove(i);
    }
}

新しいデータ構造やクラスを学ぶ必要がないためです。

15
froman

このような操作をサポートするListインターフェイスの同時実装が必要です。

java.util.concurrent.CopyOnWriteArrayList.classを試してください

7
idiotgenius

ループを繰り返し処理しているときに、remove()操作でList値を変更しようとしています。これにより、ConcurrentModificationExceptionが発生します。

以下のコードに従ってください。これにより、必要なものが実現されますが、例外はスローされません。

private String toString(List aDrugStrengthList) {
        StringBuilder str = new StringBuilder();
    List removalList = new ArrayList();
    for (DrugStrength aDrugStrength : aDrugStrengthList) {
        if (!aDrugStrength.isValidDrugDescription()) {
            removalList.add(aDrugStrength);
        }
    }
    aDrugStrengthList.removeAll(removalList);
    str.append(aDrugStrengthList);
    if (str.indexOf("]") != -1) {
        str.insert(str.lastIndexOf("]"), "\n          " );
    }
    return str.toString();
}
5
bragboy

同時コレクションクラスを使用して、コレクションの繰り返し処理中にConcurrentModificationExceptionを回避できます。たとえば、ArrayListではなくCopyOnWriteArrayListです。

ConcurrentHashMapについては、この投稿を確認してください

http://www.journaldev.com/122/hashmap-vs-concurrenthashmap-%E2%80%93-example-and-exploring-iterator