2017-02-01 49 views
2

AbstractSet.removeAll()有兩個代碼將mark設置爲已修改。摘要設置不同的邏輯

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)不是modified |= remove(i.next());作爲第一(// 1)?

我會重寫第二個(// 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; 
    } 

UPDATE1i.remove()返回void。 Update2:i.remove()會清空不受歡迎的結果集。 根據update1,update2這個重寫不起作用。

+3

它是'| =',而不是'!='!重要的區別! –

+0

鏈接已損壞。 –

+0

@StephenC謝謝。更正了鏈接:)! – Willmore

回答

2

第一次調用使用Set.remove(),第二次使用Iterator.remove()。

重點是:第一個返回布爾值,因此可以通過「或」調用set.remove()的結果來計算「最終」結果。

雖然第二個iterator.remove()不返回任何東西 - 它是一個無效的方法!因此,您需要一種不同的方法來「計算」那裏的布爾值!

+0

你是對的,它是void方法。:)我認爲它是布爾型的。謝謝! – Willmore

+0

其實,我花了幾秒鐘的時間才明白這一點。它總是有助於看看javadoc ;-) – GhostCat

4

安全地移除從Collection(該Set爲其removeAll被稱爲)元件,同時遍歷它與Iterator小號remove方法的唯一方法。使用remove(i.next())將會出現ConcurrentModificationException

另一方面,第一個循環不會遍歷要從中移除元素的Set(它會迭代通過作爲參數傳遞的Collection)。因此可以安全地調用remove(i.next())

兩個循環之間的另一個區別是:第一,remove(i.next())不能保證從Set(因爲要刪除的元素可能無法在Set)刪除任何東西,所以你要OR的所有結果調用remove來確定是否有任何內容被刪除。這就是modified |= remove(i.next());的原因。

在另一方面,使用Iterator時的刪除,你肯定知道移除的元素(這是很可能的原因Iterator的remove不返回任何東西 - 如果它沒有,那就總是返回true)因此您可以在刪除第一個元素後簡單地將modified設置爲true

編輯:

關於你的編輯,這表明重寫第二循環去除contains(i.next())檢查 - 即使不考慮在modified |= i.remove())(從Iterator的remove的返回void類型)得到的編譯錯誤,這將空而不是僅刪除Set中存在的c的元素。

+0

謝謝你的解釋:)。 – Willmore

+1

@Willmore請注意,重要的問題是'modified | = remove(i.next());'不能在第二個循環中使用(不是Iterator的remove有一個'void'返回類型) 。 – Eran