2016-05-13 11 views
0

行list.add( "3")のコメントを外すと、ConcurrentModificationExceptionがスローされます。 2つの要素に対しては正常に動作し、1または3の要素に対しては例外がスローされますか?この動作の説明はありますか?並行変更例外の不一致

import java.util.*; 

public class ConException { 

    public static void main(String[] args) { 
     List<String> list = new ArrayList<String>(); 
     list.add("1"); 
     list.add("2"); 
     //list.add("3"); 
     for(String x: list){ 
      list.remove("1"); 
     } 
     System.out.println(list); 
    } 
} 
+0

削除したい場合は、によって削除 list.remove(list.indexOf(0); – emotionlessbananas

+0

@holidayCoderこのシナリオでは動作しません。 – Kayaman

+1

@ user6328922このリンクをチェックしてください - http://www.journaldev.com/378/how-イテレータを使用している場合の避けるコンカレントな変更の修正 – Gandhi

答えて

0

反復処理中にリストを変更することはできません。
list.remove("1")のループ内にfor (String x: list)を呼び出すことはできません。
ループを削除し、単に "1"要素を削除します。

次のことで、あなたがこれを行うことができ、すべての「1」の要素を削除する場合:

while (list.remove("1")) {} 

編集:ここでは
ArrayListIteratorクラスのコードを逆コンパイルされ、それが中に使用されているため、ループ。各反復nextメソッドが呼び出された後、どこConcurrentModificationExceptionがスローすることができ

私たちの例外は、以下の条件に nextメソッドからスローされ
private class ArrayListIterator implements Iterator<E> { 
    /** Number of elements remaining in this iteration */ 
    private int remaining = size; 

    /** Index of element that remove() would remove, or -1 if no such elt */ 
    private int removalIndex = -1; 

    /** The expected modCount value */ 
    private int expectedModCount = modCount; 

    public boolean hasNext() { 
     return remaining != 0; 
    } 

    @SuppressWarnings("unchecked") public E next() { 
     ArrayList<E> ourList = ArrayList.this; 
     int rem = remaining; 
     if (ourList.modCount != expectedModCount) { 
      throw new ConcurrentModificationException(); 
     } 
     if (rem == 0) { 
      throw new NoSuchElementException(); 
     } 
     remaining = rem - 1; 
     return (E) ourList.array[removalIndex = ourList.size - rem]; 
    } 

    public void remove() { 
     Object[] a = array; 
     int removalIdx = removalIndex; 
     if (modCount != expectedModCount) { 
      throw new ConcurrentModificationException(); 
     } 
     if (removalIdx < 0) { 
      throw new IllegalStateException(); 
     } 
     System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining); 
     a[--size] = null; // Prevent memory leak 
     removalIndex = -1; 
     expectedModCount = ++modCount; 
    } 
} 

if (ourList.modCount != expectedModCount) { 
    throw new ConcurrentModificationException(); 
} 

そして、我々のmodCount変数はそう、remove反復で変更されました次のnextコールは失敗します。あなたはArrayListの中に2つの要素を持っている場合にのみ、

+0

how about list.remove(list.ind exOf(0) – emotionlessbananas

+0

@holidayCoderたくさんの可能なsolutonsがあります:あなたはうまくいくはずですが、 'list.remove(0)'は最初の要素を削除しやすくなります。 –

+0

質問は最初の要素を削除することではありません。これは、なぜ 'ConcurrentModificationException'が常にスローされないのかについてです。 – Kayaman

0

あなたのケースではConcurrentModificationException https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html

のJavaのドキュメントを読んでください、あなたはConcurrentModificationExceptionを取得する他のすべての場合には、例外を得ることはありません。

javadocで明示されているように、javaDocの状態は、JREが同時の変更が行われているかどうかによって異なり、同じことを保証する方法ではありません。

そのままフェイルファストの動作を保証することはできません注意、一般 、 非同期の同時変更の存在下で任意のハード保証をすることは不可能話す

+0

彼は文字列の配列を取得しているが、リストオブジェクトを削除しているが、実際の点は得られていない – emotionlessbananas

関連する問題