2011-11-18 18 views
5

リストを繰り返し処理している間に、リストの要素を削除する際に問題が発生しています。コード:リストから要素を動的に削除する

For (WebElement element: list){ 
    if (!element.isEnabled() || !element.isSelected()){ 
     list.remove(element); 
    } 
} 

私は、私は完全に理解してConcurrentModificationExceptionを取得。リスト内を移動するループ中に、リストから項目を削除しています。直感的に言えば、それはループの索引付けを台無しにするでしょう。

私の質問は、enabledまたはselectedでない要素をこのリストから削除する必要がありますか?

答えて

8

ループにリストから要素を削除する最も簡単な方法は、反復子を使用しての外部ように、それを反復しながらリストを修正ルーチンiterator.remove()

+0

必ずしも最も簡単なのかどうかわかりません。 'remove()'は 'Iterator 'インタフェースのオプション機能です。 'remove()'が 'Iterator 'にあり、単に 'ListIterator 'によって継承されていることにも注意してください。 – corsiKa

6

結果を使用して要素をListIteratorを使用して除去することです未定義の振る舞いであなたは明示的にイテレータを使用する必要があります:

Iterator<WebElement> iter = list.iterator(); 
while (iter.hasNext()) { 
    WebElement element = iter.next(); 
    if (!element.isEnabled() || !element.isSelected()) { 
     iter.remove(); 
    } 
} 

は、より多くのためにthis questionを参照してください。

+0

うーん、私は参照してください。だから、もし 'Iterator'を' List'に変換したいのであれば、各要素を一つずつループで追加するより簡単な方法はありますか? – jamesfzhang

+2

これは 'List'を' Iterator'に変換しません - 'Iterator'はそのリスト自体に作用するオブジェクトです - これはリストを反復するためのインターフェースです。 'iter.remove()'を呼び出すと、実際にはそのリストが変更されています。 – Claudiu

+0

うわー、それは素晴らしいです!ありがとう。 – jamesfzhang

0

ConcurrentModificationExceptionは、for-each構文がIteratorインターフェイスを使用するための単なる構文上の砂糖であるという事実から生じます。

リストイテレータには「フェイルファスト」属性があります。つまり、イテレータによって提供されたインタフェースを除いてリストに加えられた変更は、直ちにイテレータを無効にします。無効化されたイテレータを使用しようとすると、例外が発生します。

@Claudiuは既にこのコードを掲載していますが、わかりやすくするためにここにも入れます。あなたがしようとしていることをするためには、派手な構文を取り除き、裸のイテレータを使用する必要があります。

Iterator<WebElement iter = list.iterator(); 
while (iter.hasNext()) { 
    WebElement element = iter.next(); 
    if (!element.isEnabled() || !element.isSelected()) { 
     iter.remove(); 
    } 
} 
3

他にも、リストイテレータを使用することが推奨されています。それは私には有益であると判明しましたが、残念なことに、というメソッドに依存しています。これはIterable<E>インターフェイスではオプションと見なされます。 Javadocのquothが

、ネヴァーモア(強調鉱山):

ボイドのremove()

は、基になるコレクションから、反復子(任意のオペレーション) によって返された最後の要素を削除します。

これを回避するには、削除リストが役立つことがわかりました。

List<E> removed = new ArrayList<E>(); 
for(E element : list) { 
    if(someCondition) removed.add(element); 
} 
list.removeAll(removed); 

これには、removeメソッドと同様に、削除したものの履歴が表示されるという利点があります。

+0

私はこれをとても好きです(+1)。しかし、要素Eは、equalsメソッド – GETah

+1

@ GETahの適切なオーバーライドを持つ必要があります。それはそれなしでうまく動作し、さらに好ましいかもしれません。ファクトリメソッドから来てもかまいませんが、equalsメソッドの必要性は非常に少なく、参照に厳密に頼っています。 – corsiKa

+1

うわー、私はこれもたくさん好きです!ボックスの思考の外で非常に良い。 – jamesfzhang

関連する問題