現在のノードの後にオブジェクトを追加したり、現在のノードの後にオブジェクトを削除したりするときに、どのようにIterator
スローしますか。基になるコレクションへのコピーまたは参照を維持しますかConcurrentModificationException
?Iterator
5 に答える
イテレータは、基になるコレクションへの参照を維持します。要素を追加または削除すると、イテレータが不可能なインデックスのままになるか、コレクションがイテレータの「下から」変更される可能性があります。
したがって、ほとんどのコレクションは、通知せずにイテレーターを破損させるのではなく、反復中にコレクションを変更しようとするとConcurrentModificationExceptionをスローするので、予期せず破損したイテレーターになってしまうことはありません。
Iterator.remove()
契約により、反復中にコレクションを変更することは許可されていません ( et alを使用する場合を除く)。
これを行うとランダムに失敗する代わりに、コレクションは変更された回数を追跡し、ConcurrentModificationException
同時変更を検出するとスローするのに十分です。
削除するには、次のように iterator.remove() を使用できます。
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Object object = iterator.next();
/* ... */
if (condition) {
iterator.remove();
}
追加するために、次のように単純な Iterator を ListIterator に置き換えることができます。
ListIterator<Object> iterator = list.listIterator();
iterator.add(new Object());
もちろん、イテレータには基になるコレクションへのリンクがあり、これによりコピーが回避されます。たとえば、ArrayListイテレータ(ListItr)のソースコードを見ると、ほとんどの場合、リストへのリンクとカーソルが含まれていることがわかります。
したがって、スレッド間でイテレータを共有したり、反復しているコレクションを変更したりしないでください。