2017-02-01 1 views
2

AbstractSet.removeAll()には、修正済みとしてマークするコードが2つあります。概要異なる論理を設定する

AbstractSetは

public boolean removeAll(Collection<?> c) { 
     boolean modified = false; 

     if (size() > c.size()) { 
      for (Iterator<?> i = c.iterator(); i.hasNext();) 
       modified |= remove(i.next()); //1 
     } else { 
      for (Iterator<?> i = iterator(); i.hasNext();) { 
       if (c.contains(i.next())) { 
        i.remove();   //2 
        modified = true;  //2 
       } 
      } 
     } 
     return modified; 
    } 

は何秒(// 2)(// 1)第一としてmodified |= remove(i.next());ではないことの背後にあるロジック可能性がありますか?

2番目の(// 2)は最初の(// 1)と同じになるように書き直して、余分なチェック(contains(i.next()))がないようにします。

public boolean removeAll(Collection<?> c) { 
     boolean modified = false; 

     if (size() > c.size()) { 
      for (Iterator<?> i = c.iterator(); i.hasNext();) 
       modified |= remove(i.next()); //1 
     } else { 
      for (Iterator<?> i = iterator(); i.hasNext();) { 
       i.next(); 
       modified |= i.remove()); //2 
      } 
     } 
     return modified; 
    } 

アップデート1:無効i.remove()戻ります。 Update2:i.remove()は、歓迎された結果でないセットを空にします。 update1、update2に基づいて、このリライトは機能しません。

+3

'| ='ではなく、 '!='!重要な違い! –

+0

リンクが壊れています。 –

+0

@StephenCありがとうございます。リンクを修正しました:)! – Willmore

答えて

2

最初の呼び出しでは、Set.remove()が使用され、2番目の呼び出しではIterator.remove()が使用されます。

ポイントは次のとおりです。最初のものはブール値を返すので、set.remove()の呼び出しの結果を「or」することによって「最終的な」結果を計算できます。

一方、2番目のiterator.remove()は何も返しません。これはvoidメソッドです!したがって、そこにブール値を「計算する」別の方法が必要です。

+0

あなたはそれが正しい方法ですvoid method :)私はそれがブール値であると仮定しました。ありがとうございました! – Willmore

+0

実際には、それもまた理解するのに数秒かかりました。常にjavadoc ;-)を見るのに役立ちます – GhostCat

4

Iterator S remove方法である繰り返し処理しながら安全にCollectionremoveAllが呼び出されたためSet)から要素を削除する唯一の方法。 remove(i.next())を使用すると、ConcurrentModificationExceptionがスローされます。

一方、最初のループは、要素が削除されるSetを反復しません(引数として渡されたCollectionを反復します)。したがって、remove(i.next())を安全に呼び出すことができます。

二つのループの間にもう1つの違いは、最初に、remove(i.next())は(削除する要素がSetではないかもしれないので)Setから何かを削除することは保証されませんので、あなたがしたいORのすべての結果ということですremoveが呼び出され、何かが削除されたかどうかが判定されます。それがmodified |= remove(i.next());の理由です。一方、

「sは、あなたが要素が削除されたことを確認するために知っている、削除( Iteratorその理由はおそらく理由です」 Iteratorを使用しての削除は何も返さない - それがなかったならば、それは常に trueを返します)最初の要素を削除した後に modifiedtrueに設定するだけです。

EDIT:あなたの編集について

contains(i.next())チェック取り除くために第二のループを書き換える示唆 - さえ(Iteratorの削除のボイド戻り値の型から生じる)modified |= i.remove())でコンパイルエラーを無視し、空になりSetにあるcの要素だけを削除するのではなく、Setを削除します。

+0

ありがとうございました:)。 – Willmore

+1

@Willmore重要な問題は、 'modified | = remove(i.next());'は2番目のループで使用できないということです( 'Iterator'のremoveは' void'戻り型を持ちません) 。 – Eran

関連する問題