2013-04-13 9 views
21

コレクションを反復しながらコレクションを削除する最も安全な方法は、まずIteratorを取得し、必要に応じてループを実行して削除することです。Iteratorのremoveメソッドが実際にオブジェクトを削除する方法

私が理解したい、と残念なことにに関する深い技術的な説明を発見していない、この除去が行われたか、もし
は何
Iterator iter=Collection.iterator(); 
while(iter.hasNext()){ 
    Object o=iter.next() 
    if(o.equals(what i'm looking for)){ 
     iter.remove(); 
    } 
} 

for(Object o:myCollection().getObjects()){ 
    if(o.equals(what i'm looking for)){ 
     myCollection.remove(o); 
    } 
} 

は何、ConcurrentModificationExceptionがスローされます「技術用語で」Iterator.remove()は何ですか?オブジェクトを削除してループを解除し、ループを再開しますか?

私は公式ドキュメントで参照してください。

は、「現在の要素を削除し 試みは次の ()への呼び出しによって先行されていないことremove()を呼び出すために行われた場合IllegalStateExceptionをスローします。」

部分は、私は「通常の」ループで起こって正確に同じような状況を考えるになり、「現在の要素を削除します」=>(等号のテストを行い、必要に応じて削除)が、なぜイテレータループがありますConcurrentModification-安全?

+0

あなたが自分で見ることができます。https:/ /gist.github.com/kibotu/e480bd7505615a7311a6 –

答えて

14

Iteratorが要素を削除する方法は、実装によって異なりますが、これはコレクションによって異なる場合があります。確かに、それはあなたがにしているループを破壊しない、私はちょうどどのように実装されるかArrayListのイテレータを見て、ここでのコードだしました:。だから、

public void remove() { 
    if (lastRet < 0) 
     throw new IllegalStateException(); 
    checkForComodification(); 

    try { 
     ArrayList.this.remove(lastRet); 
     cursor = lastRet; 
     lastRet = -1; 
     expectedModCount = modCount; 
    } catch (IndexOutOfBoundsException ex) { 
     throw new ConcurrentModificationException(); 
    } 
} 

それは同時変更をチェックし、を削除公共のArrayList を使用して要素を削除メソッドを呼び出し、リストの変更のカウンターをインクリメントして、次の反復でConcurrentModificationExceptionがスローされないようにします。

+1

'lastRet'とは何ですか? – m0skit0

+1

イテレータによって返された最後の要素のインデックス。この要素はリストから削除されたため、-1に設定されています。 –

+0

Javaはちょっと錆びますが、 'ArrayList.this.remove(lastRet)'は何ですか? 'ArrayList.this'を書く必要があるのはなぜですか?それは内なるクラスか何かですか? –

17

iteratorがhasNext()とnext()のために何を返すべきかを知っていなければならないため、リストを反復処理中にリストを変更できないのはなぜですか。これがどのように行われるか

は実装固有のものですが、あなたはArrayListの/ AbstractList/LinkedListのなどのソースコードを見て持つことができ

はまた、いくつかの状況であなたは、代替として、このようないくつかのコードを使用することができます:

List<Foo> copyList = new ArrayList<>(origList); 
for (Foo foo : copyList){ 
    if (condition){ 
    origList.remove(foo); 
    } 
} 

しかしコレクションは(のみ浅いコピー)をコピーする必要があり、削除する要素を検索する必要があるため、このコードは、おそらくわずかに遅く実行されます。

はまた、あなたが直接イテレータを使用している場合、これは、変数のスコープを限定としてではなくwhileループのforループを使用することをお勧めしますのでご注意:

for (Iterator<Foo> iterator = myCollection.iterator(); iterator.hasNext();){ 
... 
} 
関連する問題