2

次のモックアップコードはConcurrentModificationException、私が変更しているセットを反復処理しているという事実のために、(私が理解しているように) で終了します。

Set<String> data = new HashSet<String>();
data.add("a=1");
data.add("b=2");
data.add("c=3");
data.add("d=4");

for (String s : data) {
    data.remove(s);
}

しかし、なぜそれは正確ですか?明確にするのを手伝ってください

4

4 に答える 4

2

data.remove(s)反復処理中にコレクションを ( を呼び出して) 変更しているという理由だけで、例外がスローされています。一般に、Java コレクションには、値を繰り返し処理している間は変更できないという要件があります。

公式ドキュメントから:

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

于 2011-08-30T18:50:35.510 に答える
2

イテレータの契約に違反しています。ConcurrentModificationExceptionjavadocから、

1 つのスレッドが、オブジェクトのコントラクトに違反する一連のメソッド呼び出しを発行すると、オブジェクトはこの例外をスローする可能性があります。たとえば、フェイルファスト反復子を使用してコレクションを反復処理しているときに、スレッドがコレクションを直接変更すると、反復子はこの例外をスローします。

于 2011-08-30T18:50:40.463 に答える
1

これは、コンパイラが実際にを挿入してIteratorから、従来のforループを使用して要素を反復処理するためです。Collectionイテレータが設立された場所を変更すると、動作が不確定になります。これを防ぐために、ConcurrentModificationExceptionがスローされます。

こちらもご覧ください

項目7.反復中にリストを変更しないでください。for-each構文は、同等の基本的なforループで使用されるイテレータへの直接アクセスを提供しませんが、リストの他のメソッドを直接呼び出すことでリストを変更できます。これを行うと、プログラムの動作が不確定になる可能性があります。特に、コンパイラーが挿入したiterator()の呼び出しがフェイルファストのイテレーターを返す場合、java.util.ConcurrentModificationExceptionランタイム例外がスローされる可能性があります。ただし、これはベストエフォートベースでのみ行われ、例外がスローされたときにバグを検出する手段を除いて、信頼することはできません。

または、言語仕様のforeachループのセクション。

于 2011-08-30T18:55:49.130 に答える
1

Set から要素を削除するには、 Iterator を使用する必要があります

于 2011-08-30T18:50:19.567 に答える