10

私はこの例外に苦しんでいます。私のコードの問題は何ですか?Person の重複した名前を別の名前で区切りたいだけですArrayList

public class GlennTestMain
{

    static ArrayList<Person> ps;

    static ArrayList<Person> duplicates;
    public static void main(String[] args)
    {
        ps = new ArrayList<GlennTestMain.Person>();

        duplicates = new ArrayList<GlennTestMain.Person>();

        noDuplicate(new Person("Glenn", 123));
        noDuplicate(new Person("Glenn", 423));
        noDuplicate(new Person("Joe", 1423)); // error here


        System.out.println(ps.size());
        System.out.println(duplicates.size());
    }

    public static void noDuplicate(Person p1)
    {
        if(ps.size() != 0)
        {
            for(Person p : ps)
            {
                if(p.name.equals(p1.name))
                {
                    duplicates.add(p1);
                }
                else
                {
                    ps.add(p1);
                }
            }
        }
        else
        {
            ps.add(p1);
        }
    }

    static class Person
    {
        public Person(String n, int num)
        {
            this.name = n;
            this.age = num;
        }
        String name;
        int age;
    }



}

ここにスタックトレースがあります

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at hk.com.GlennTestMain.noDuplicate(GlennTestMain.java:41)
at hk.com.GlennTestMain.main(GlennTestMain.java:30)
4

3 に答える 3

19

collection繰り返している を変更することはできません。それは . をスローする可能性がありConcurrentModificationExceptionます。時々うまくいくかもしれませんが、いつもうまくいくとは限りません。

リストに何かを追加または削除する場合は、リストにIterator、 またはを使用する必要がありListIteratorます。メソッドを使用ListIterator#addして、リストに何かを追加します。であっても、またはiteratorを使用しようとすると、違いがないため、その例外が発生します。のメソッドを使用する必要があります。List.addList.removeiterator

これらの投稿を参照して、使用方法を理解してください: -

于 2012-10-30T06:24:37.657 に答える
7

理由?

ArrayListによって返されるイテレータは本質fail-fast的です。

このクラスの反復子とlistIteratorメソッドによって返される反復子はfail-fas次のとおりです。反復子が作成された後、反復子自体の remove または add メソッド以外の方法でリストが構造的に変更された場合、反復子はConcurrentModificationException. したがって、同時変更に直面した場合、反復子は、将来の不確定な時点で恣意的で非決定論的な動作を危険にさらすのではなく、迅速かつ明確に失敗します。

この反復子は、使用していないときにどこから来るのですか?

コレクションの強化された for ループが使用されるため、反復中にメソッドをIterator呼び出すことはできません。add

したがって、ループは以下と同じです

for (Iterator<Entry> i = c.iterator(); i.hasNext(); ){   

解決策は何ですか?

iterator.add();暗黙的ではなく明示的に反復子に基づいてループを呼び出して変更できます。

    String inputWord = "john";
    ArrayList<String> wordlist = new ArrayList<String>();
    wordlist.add("rambo");
    wordlist.add("john");
    for (ListIterator<String> iterator = wordlist.listIterator(); iterator
            .hasNext();) {
        String z = iterator.next();
        if (z.equals(inputWord)) {
            iterator.add("3");
        }
    }
    System.out.println(wordlist.size());

どこでもっと読むことができますか?

  1. For-Each ループ
  2. ArrayList Java ドキュメント
于 2012-10-30T06:30:35.173 に答える
0

ACC。Java ドキュメントへ:

フェイルファスト反復子を使用してコレクションを反復処理しているときに、スレッドがコレクションを直接変更すると、反復子はこの例外をスローします。

強化された For loopPersonを使用してオブジェクトを反復しながらオブジェクトを追加しようとしています。

次の変更を行うことができます。

boolean duplicateFound = false;
for(Person p : ps)
{
    if(p.name.equals(p1.name))
    {
        duplicates.add(p1);
        duplicateFound = true;
    }
}

if( ! duplicateFound)
{
    ps.add(p1);
}
于 2012-10-30T06:29:24.307 に答える