45

この小さなコードがあり、同時変更の例外が発生します。同時修正が実行されていないのに、なぜそれを取得し続けるのか理解できません。

import java.util.*;

public class SomeClass {
    public static void main(String[] args) {
        List<String> s = new ArrayList<>();
        ListIterator<String> it = s.listIterator();

        for (String a : args)
            s.add(a);

        if (it.hasNext())
            String item = it.next();

        System.out.println(s);
    }
}
4

9 に答える 9

54

を回避するConcurrentModificationExceptionには、次のようにコードを記述する必要があります。

import java.util.*;

public class SomeClass {

    public static void main(String[] args) {
        List<String> s = new ArrayList<String>();

        for(String a : args)
            s.add(a);

        ListIterator<String> it = s.listIterator();    
        if(it.hasNext()) {  
            String item = it.next();   
        }  

        System.out.println(s);

    }
}

を使用するjava.util.ListIteratorと、反復中にリストを変更できますが、リストを作成してから使用するまでの間に変更することはできません。

于 2009-09-30T05:14:57.030 に答える
53

同時修正が実行されていないのに、なぜそれを取得し続けるのか理解できません。

イテレーターを作成してからイテレーターの使用を開始するまでの間に、反復されるリストに引数を追加しました。これは同時修正です。

    ListIterator<String> it = s.listIterator();  

    for (String a : args)
        s.add(a);                    // concurrent modification here

    if (it.hasNext())
        String item = it.next();     // exception thrown here

リストへの要素の追加が完了したら、イテレータを作成します。

    for (String a : args)
        s.add(a); 

    ListIterator<String> it = s.listIterator();  
    if (it.hasNext())
        String item = it.next();
于 2009-09-30T05:09:01.723 に答える
12

JavaDocから: ConcurrentModificatoinException の場合: 「通常、別のスレッドがコレクションを反復しているときに、あるスレッドがコレクションを変更することは許可されていません」。

これは単純に、まだ開いているイテレータがある場合、イテレータ ループが壊れるため、リストを変更できないことを意味します。ListIterator<String> it = s.listIterator();for ループの後まで移動してみてください。

于 2009-09-30T05:07:59.400 に答える
8

基礎となるリストが変更された後、反復子を反復処理し続けることはできません。ここでは、 にいくつかのアイテムを追加する前にイテレータを作成し、追加後にsahasNext()と aを実行して、next()ConcurrentModificationException

于 2009-09-30T05:07:11.177 に答える
5

上記の解決策が正しく機能しない場合。新しい項目を追加すると同時に List を反復するために、古い for ループを使用できます。以下の例を参照してください。

import java.util.*;

public class SomeClass {
    public static void main(String[] args) {
        ArrayList<AClass> aList = new ArrayList<AClass>(); // we will iterate this


        // this will cause ConcurrentModificationException. 
        // Since we are iterating the list, at the same time modifying it.
        /*for(AClass a: aList){
           aList.add(someMethod(a));
        }*/

        // old fashion for-loop will help
        int limit = aList.size();
        for(int i=0; ctr<limit; ++i){
           AClass a = aList.get(i);
           aList.add(someMethod(a));
        }


    }
}
于 2013-12-11T11:05:40.143 に答える
1

オラクルのドキュメントページをご覧ください。

public class ConcurrentModificationException
extends RuntimeException

この例外は、そのような変更が許可されていない場合に、オブジェクトの同時変更を検出したメソッドによってスローされる可能性があります

この例外は、オブジェクトが別のスレッドによって同時に変更されたことを常に示すわけではないことに注意してください。1 つのスレッドが、オブジェクトのコントラクトに違反する一連のメソッド呼び出しを発行すると、オブジェクトはこの例外をスローする可能性があります。たとえば、フェイルファスト反復子を使用してコレクションを反復処理しているときに、スレッドがコレクションを直接変更すると、反復子はこの例外をスローします

あなたの場合、イテレータを作成した後にコレクションを変更したため、例外が発生しました。

Stephen Cの回答に従ってコードを変更すると、このエラーは発生しません。

于 2016-03-02T00:49:18.300 に答える