2012-04-28 3 views
1

以下のようなベクトルからリストを削除しようとしました。Vectorからjava.util.ConcurrentModificationExceptionを取得するリストを削除する

public class StringVectorTest { 

private final List<String> stringVector = new Vector<String>(); 

@Test 
public void listRemoveTest(){ 

    List<String> list = stringVector.subList(0, 2); 

    stringVector.removeAll(list); 

    Assert.assertEquals(stringVector.size(), 3); 
} 

@Before 
public void fillList(){ 
    stringVector.add("ABC"); 
    stringVector.add("DEF"); 
    stringVector.add("GEH"); 
    stringVector.add("IJK"); 
    stringVector.add("LMN"); 
} 

}

私は誰も私がどのように教えてくださいすることができ、このConcurrentModificationExceptionを克服するためにIteratorを使用する必要があることを知って、私は以下のエラー

java.util.ConcurrentModificationException 
at java.util.SubList.checkForComodification(AbstractList.java:752) 
at java.util.SubList.listIterator(AbstractList.java:682) 
at java.util.AbstractList.listIterator(AbstractList.java:284) 
at java.util.SubList.iterator(AbstractList.java:678) 
at java.util.AbstractCollection.contains(AbstractCollection.java:82) 
at java.util.Collections$SynchronizedCollection.contains(Collections.java:1563) 
at java.util.AbstractCollection.removeAll(AbstractCollection.java:336) 
at java.util.Vector.removeAll(Vector.java:853) 

に取得していますテストを実行しながら、私はそれを効率的な方法で/ベストプラクティスで使うべきですか?

ありがとうございます。

答えて

3

は、以下のようにそれを実行します。

public void listRemoveTest() { 
    stringVector.subList(0, 2).clear(); 
    Assert.assertEquals(stringVector.size(), 3); 
} 
+0

おかげで答えをたくさん。出来た。 – Sam

2

ConcurrentModificationExceptionさんのjavadocから:

この例外は、そのような変更が許可されていない場合、オブジェクトの同時変更を検出したメソッドによってスローされる可能性があります。 たとえば、あるスレッドがCollectionを変更している間に、別のスレッドがそれを反復している間は、一般には許容できません。一般に、これらの状況では、反復の結果は未定義です。この動作が検出された場合、Iterator実装(JREによって提供されるすべての汎用コレクション実装の実装を含む)によっては、この例外がスローされる可能性があります。これを行う反復子は、フェイル・ファースト・イテレータとして知られています。これらの反復子は、将来的に不確定な時間に任意の非決定論的な動作を危険にさらすのではなく、迅速かつきれいに失敗します。

この例外は常にオブジェクトが同時に異なるスレッドによって改変されていることを示すものではないことに留意されたいです。 1つのスレッドがオブジェクトの契約に違反する一連のメソッド呼び出しを発行すると、オブジェクトはこの例外をスローする可能性があります。例えば、フェイル・ファースト・イテレータを使用してコレクションを反復している間にスレッドがコレクションを直接変更した場合、イテレータはこの例外をスローします。

後者はまさにあなたがやっていることです(投稿したスタックトレースを参照してください)。 subListメソッドはリストのビューを返します。このメソッドから返されるリストはstringVectorによってサポートされているため、返されたリストの非構造的な変更はstringVectorに反映され、その逆もあります。

だから、要素を削除するには、この「ビュー」を使用する必要がありますので、イテレータと

@Test 
public void listRemoveTestClearingSubList(){ 
    stringVector.subList(0, 2).clear();  
    Assert.assertEquals(stringVector.size(), 3); 
} 

は少しトリッキーと醜いです:

@Test 
public void listRemoveTestClearingWithIterator(){ 
    Iterator<String> it = stringVector.iterator(); 
    for (int i = 0; i < 2 && it.hasNext(); i++) { 
     it.next(); 
     it.remove(); 
    } 

    Assert.assertEquals(stringVector.size(), 3); 
} 
+0

大変ありがとうございました。できます。 :) – Sam