2017-02-01 26 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