foreachループはコレクション内の各項目の値を変更できません
2547 ワード
import java.util.ArrayList;
import java.util.List;
public class foclass4 {
/**
* @param args
*/
public static void main(String[] args) {
List<String> lists = new ArrayList<String>();
lists.add("ad");
lists.add("dv");
lists.add("dvs");
lists.add("adf");
for(String s:lists)
{
if(s.equals("ad"))
{
lists.remove(s);
continue;
}
System.out.println(" --"+s);
}
}
}
エラー:
Exception in thread "main"java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at foclass4.main(foclass4.java:13)
理由:
foreachを使用する構文の場合、foreachという構文を使用するには、このインタフェースIteratorを継承する必要があります.このインタフェースは簡単です.反復器Iteratorを返すことです.反復器には急速に失敗する特徴があります.反復器によって集合内の要素を除去することはできません.
詳細JDK
複数のスレッドが同時にArrayListインスタンスにアクセスし、少なくとも1つのスレッドが構造的にリストを変更した場合、外部同期を維持する必要があります.(構造上の変更とは、1つ以上の要素を追加または削除する操作、または最下位の配列のサイズを明示的に調整することです.要素の値を設定するだけでは構造上の変更ではありません.)これは、一般に、リストを自然にカプセル化したオブジェクトを同期することによって行われる.このようなオブジェクトが存在しない場合はCollectionsを使用する.synchronizedListメソッドは、リストを「パッケージ」します.これは、リストへの予期せぬ同期アクセスを防ぐために、作成時に完了することが望ましい.
List list = Collections.synchronizedList(new ArrayList(...)); このようなiteratorメソッドとlistIteratorメソッドで返される反復器は、反復器を作成した後、反復器は反復器自体のremoveメソッドまたはaddメソッドで構造的にリストを変更しない限り、リストをいつでも任意の方法で変更すると、反復器はConcurrentModificationExceptionを放出します.したがって、反復器は、将来の不確定な時間に任意の不確定な動作が発生するリスクを冒すのではなく、同時修正に直面してすぐに完全に失敗します.
反復器の迅速な失敗は、一般的には、非同期の同時修正が発生するかどうかについて、いかなるハードウェア保証もできないため、保証されません.高速障害反復器は、C o n c u r r e n tModificationExceptionを放出するために最善を尽くします.したがって、このような反復器の正確性を向上させるために、この異常に依存するプログラムを作成するのは間違っている.反復器の迅速な失敗行為はバグの検出にのみ使用されるべきである.
反復から削除可能
List<String> lists = new ArrayList<String>();
lists.add("ad");
lists.add("dv");
lists.add("dvs");
lists.add("adf");
Iterator<String> it=lists.iterator();
while(it.hasNext())
{
String str=it.next();
if("ad".equals(str))
{
it.remove();
}
else
{
System.out.println(str);
}
}
結果:
dv
dvs
adf