2011-05-20 3 views
11

この小さなコードは、奇妙にも、上記のExceptionをスローします。 はまた、ウェブを中心に掲載のコードを見て、これは正しいと思わ:なぜIterator.next()がConcurrentModificationExceptionをスローするのですか

import java.util.ArrayList; 
import java.util.Iterator; 

public class IteratorTest { 

    ArrayList<Integer> arr = new ArrayList<Integer>(); 

    Iterator i = arr.iterator(); 

    public void show() { 
     arr.add(2); 
     arr.add(5); 
     arr.add(9); 

     while(i.hasNext()){ 
      System.out.println(i.next()); 
     } 
    } 
} 

任意のアドバイスはありますか? おかげ

+0

http://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re – Raedwald

答えて

12

このコール:あなたのArrayListにすべての書き込みをやった後

Iterator i=arr.iterator(); 

はする必要があります。あなたはiterator()経由Iteratorを取得し、next()を呼び出す間のバッキングリストを変更したので

Iterator i=arr.iterator(); 
while(i.hasNext()) { 
... 
} 
+0

Thxをanbhavaの複製、変更あれば基本的にイテレータ自体は更新されませんイテラブルが実行されます。私はこのthxを知らなかった – JBoy

+1

私はループのwhileループよりもイテレータ変数 'i'の範囲を制限していると思っています。 –

4

それはです:あなたのコード内ので

は、あなたがこのように繰り返しを開始し直前にこれを行います。

イテレータの典型的な使用法は次のとおりです。まだ

for (Iterator<Integer> iter=arr.iterator(); iter.hasNext();) { 
    Integer element = iter.next(); 
} 

以上、のために、各ループの新しいを使用します。

for (Integer element: arr) { 
} 

の外のコレクションへの追加を実行するようにしてくださいループ。

2

オブジェクトのインスタンス化時にIteratorを定義しています(IteratorTest)。 ArrayListarrにいくつかのデータを追加します。

これでリストが変更されました。したがって、Iteratorの状態は無効です。

Iteratorを使用しないでArrayListを変更することはできません。Iteratorを使用しないでください。

0

回答4は技術的には正しいですが、または "each for"ループがwhile()ループの代わりに使用されているためではありません。これは、メソッドではなく、クラス内のイテレータの宣言されたスコープの問題です。まず、2つのメソッドの動作を見てみましょうhasNext()next()

hasNext()メソッドは内部カーソル(インデックス)を単に照会します。 next()は実際にカーソルを進めるので、例外を発生させる可能性のある「変更」です。 next()が使用されているメソッド外で宣言されて割り当てられたイテレータを使用しようとすると、コードはfor(;;)またはwhile()であるかどうかに関係なく、最初のnext()に例外がスローされます。

Answer 4および8では、イテレータはメソッド内でローカルに宣言され、消費されます。 for(;;)のコンストラクトでは、ループが実行される前にイテレータを初めて宣言して割り当てることができます(イテレータのスコープはfor(;;)になり、暗黙的にメソッド内で「安全」になります)。 for(;;)のイディオムは文法的により洗練されており、最も低いレベルの実行では、完全にfor(;;)ループ内にあることに同意します。

Answer 8は正しいです。イテレータはメソッド内でローカルに割り当てられ、使用されるからです。

しかし、ちょうど議論のために、以下の方法使用してwhile()文はスコープと参照観点から「安全」と非修正、構文的に正しいです:クラス定義 で

どこか.. 。

どこかに、クラスのコンストラクタで
ArrayList<String> messageList; 

messageList = new ArrayList<String>(); 

メソッドを追加...

public printMessages () 
{ 

    Iterator<String> messageIterator = messageList.iterator(); 

    while (messageIterator.hasNext()) 
    { 
    System.out.println(messageIterator.next()); 
    } 

    System.out.flush(); 

} 
関連する問題