質問
別のコレクションのコンテンツに基づいて、Javaのコレクションから最初のコレクションから不特定の要素を削除する必要があります。これは非常にシンプルに見えますが、問題です。
これは私が書きたい方法の頭です
private void screenblacknameList(list <sharedboardsmswrapper>ソース、リスト<BlackNamaListModel> BlackNameList)
これが物事です。ソースコレクションは、いくつかの表示データ要素を保存します。 BlackNameListコレクションは、ブラックリストリストを保存します。ブラックリストテーブルに基づいて、ソースコレクションのブラックリストに登録されたユーザーのデータを削除する必要があります。
この問題の解決策は非常に簡単に思えます。
最初に各ステートメントに削除するために使用します。
for(sharedboardsmswrapper tmpsharedboardsmswrapper:source){for(blacknameListmodel tmpblacknameListmodel:blacknameList){if(tmpsharedboardsmswrapper.getSource()。 source.remove(tmpsharedboardsmswrapper);壊す; }}}非常に簡単な質問!私はひそかに笑った、
テスト…
私が驚いたのは、このコードが実際に例外を投げたということでした
java.util.ConcurrentModificationException。
JDK6マニュアルを表示します
public concurrentmodificationexceptionはruntimeexceptionを導きます
この例外は、メソッドがオブジェクトの同時変更を検出するが、そのような変更を許可しない場合にスローされます。
たとえば、スレッドがコレクションを繰り返す場合、別のコレクションを線形に変更することは許可されていません。通常、これらの場合、反復の結果は不確かです。この動作が検出された場合、一部のイテレーターの実装(JREが提供するすべての共通コレクション実装を含む)は、この例外をスローすることを選択できます。この操作を実行するイテレーターは、将来のある時点で任意の不確実な行動のリスクを危険にさらすことなく非常に迅速に失敗するため、高速障害反復剤と呼ばれます。
この例外は、オブジェクトが別のスレッドによって同時に変更されたことを常に示しているわけではないことに注意してください。単一のスレッドがオブジェクトの契約に違反するメソッドコールのシーケンスを発行すると、オブジェクトはこの例外をスローする場合があります。たとえば、高速障害イテレーターを使用してコレクションを反復すると、スレッドがコレクションを直接変更する場合、イテレーターはこの例外をスローします。
一般的に、同期外の同時修飾があるかどうかを難しい保証をすることは不可能であるため、イテレーターの速い故障動作を保証できないことに注意してください。迅速な障害操作はConcurrentModificationExceptionを投げるために最善を尽くします。したがって、このような操作の正確性を改善するために、この例外に依存するプログラムを作成することは間違っています。正しい方法は次のとおりです。ConcurrentModificationException ConcurrentModificationException 、バグの検出にのみ使用する必要があります。
JavaのFor each実際には処理にIteratorを使用します。 Iteratorでは、 Iteratorの使用中にコレクションを削除することはできません。そして、私がfor each参加したとき、私はコレクションの要素を削除したため、 IteratorはConcurrentModificationExceptionをスローしました。
正直にループに従来のものしか使用できないようです!
for(int i = 0; i <source.size(); i ++){sharedboardsmswrapper tmpsharedboardsmswrapper = source.get(i); for(int j = 0; j <blacknameList.size(); j ++){blacknameListmodel tmpblacknameListmodel = blacknameList.get(j); if(tmpsharedboardsmswrapper.getSource()。壊す; }}}今は大丈夫です!自信を持ってテストを押してください...
かすか!どうしたの?どのようにしてデータを間違えますか?
デバッグ追跡の後、セットが要素を削除すると、セットのサイズが小さくなり、インデックスが変更されることがわかりました!
どうすればいいですか?私はこのような小さな問題に無力になりません!
Iteratorを使用して、コレクション内の要素を削除します
JDKマニュアルのIteratorインターフェイスを確認し、削除方法もあることを確認してください。
取り除く
void remove()
イテレーターによって返された最後の要素を削除します。コレクションは、イテレーター(オプション操作)が指し示しています。この方法は、次に電話ごとに1回のみ呼び出すことができます。この方法を呼び出す以外の方法を使用して、イテレーターが指すコレクションによってイテレーターが変更されている場合、イテレーターの動作は不確かです。
投げる:
UnsupportedOperationException -Iteratorが削除操作をサポートしていない場合。
IllegalStateException次のメソッドが呼び出されていない場合、または次のメソッドへの最後の呼び出し後に削除メソッドが呼び出された場合。
最終コードを正しい:
/ ** *@paramsource *@paramblacknameList */ privatevoid screenblacknameList(list <sharedboardsmswrapper>ソース、リスト<blacknameListmodel> blacknameList){iterator <sharedboardsmswrapper> sourceit = source.iterator(); while(sourceit.hasnext()){sharedboardsmswrapper tmpsharedboardsmswrapper = sourceit.next(); iterator <BlackNameListModel> BlackNameListit = BlackNameList.iterator(); while(blacknameListit.hasnext()){blacknameListmodel tmpblacknameListmodel = blacknameListit.next(); if(tmpsharedboardsmswrapper.getSource()。壊す; }}}}} next()イテレータのremove()複数回呼び出すことはできないことに注意してください。それ以外の場合、例外がスローされます。
コレクション内の要素を削除する最も簡単な方法は、 Iterator 's remove()メソッドを使用することです!
ArrayListクラスによって提供されたイテレーターがどのように実装されているかを見てみましょう。
privateclass ITRは、Iterator <e> { /**これを実装します。これは、ポインターまたはカーソルに相当する要素のインデックスです。これは、リストのデータ要素にアクセスするために使用します。 *IndexOfElementToBereTurnedBySubからのCalltonext。 */ intcursor = 0; /** *indexOfElementReturnedByMostRecentCalltonextor *以前。 resetto -1ifthiselementisdeletedbyacall *toremove。 /**外部クラスアレイリストのプロパティ:保護された一時的なint modcount = 0;アレイリストが他のスレッドによって同時に変更されているかどうかを観察するために使用されます。一貫性がない場合は、同期例外がスローされます。 *himodcountvaluethattheteratorbelievelievelievelievevethatthebacking *listshouldhave。この期待が溶解した場合、theiterator *はConcurrentmodificationを検出します。 */intexpectedModCount = modCount; //カーソルがリストのサイズに達していない場合、まだ要素があります。 publicboolean hasnext(){returncursor!= size(); } //現在の要素を返してから+1をカーソルします。最近のインデックス=返された要素のインデックス。 public e next(){checkforcomodification(); {e next = get(cursor); Lastret = cursor ++;次に戻ります。 } catch(indexoutofboundsexception e){checkforcomodification(); Slownew nosuchelementexception(); }}/*要素を削除します。これは、現在の要素を削除してCursor-1を配置することを意味します。なぜなら、リストはすべての要素を前の要素に移動するからです。 */ publicVoid remove(){if(lastret == -1)thrownew IllegalStateException(); checkforcomodification(); try {abstractlist.this.remove(lastret); if(lastret <cursor)cursor-;ラストレット= -1; expectsModCount = modCount; } catch(indexoutofboundsexception e){thrownew concurrentModificationException(); }} finalvoid checkforcomodification(){if(modcount!= expectsmodcount)shrownew concurrentModificationException(); }}要約します
ご覧のとおり、イテレーターは要素を削除し、カーソルを正しいシートにリセットします。他のスレッドが同時にセットを変更しない限り、問題はありません。上記はこの記事に関するものです。Javaを学ぶのが誰でも役立つことを願っています。