抽象设置不同的逻辑

AbstractSet different logic

AbstractSet.removeAll() 中有两个代码将集标记为已修改。

抽象集是

   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) 重写为与第一个 (//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;
    }

Update1: i.remove() returns 无效。 Update2: i.remove() 将清空不受欢迎结果的集合。 基于update1,update2这个重写是行不通的。

在遍历 Collection(调用 removeAllSet )中安全删除元素的唯一方法是使用 Iterators remove方法。使用 remove(i.next()) 将抛出 ConcurrentModificationException.

另一方面,第一个循环不会遍历要从中删除元素的 Set(它遍历作为参数传递的 Collection)。因此remove(i.next())可以安全调用。

这两个循环的另一个区别是,在第一个循环中,remove(i.next()) 不能保证从 Set 中删除任何内容(因为要删除的元素可能不在 Set),因此您想对 remove 调用的所有结果进行或运算以确定是否删除了任何内容。这就是 modified |= remove(i.next());.

的原因

另一方面,当使用 Iterator 的删除时,您肯定知道一个元素已被删除(这可能是 Iterator 的删除没有 return 任何东西 - 如果有,它总是 return true) 所以你可以在删除第一个元素后简单地将 modified 设置为 true

编辑:

关于您的编辑,建议重写第二个循环以删除 contains(i.next()) 检查 - 甚至忽略 modified |= i.remove()) 中的编译错误(由 [= 的 void return 类型导致13=] 的删除),这将清空 Set 而不是仅删除 Set.

中存在的 c 的元素

第一个调用使用 Set.remove(),第二个调用 Iterator.remove()。

要点是:第一个 return 一个布尔值,因此 "final" 结果可以通过 "or'ing" 调用 set.remove( ).

而第二个 iterator.remove() 没有 return 任何东西 - 它是一个无效的方法!因此,您需要一种不同的方法来 "compute" 那个布尔值!