3

AbstractCollection的addAll()实现如下:

public boolean addAll(Collection<? extends E> c) { 
    boolean modified = false;
    for (E e : c) if (add(e)) modified = true; 
    return modified;
}

因此,如果参数中的c是 3 个元素的集合,则可能是添加了前 2 个元素,但由于某种我现在想不出的原因未添加第 3 个元素。

在这种情况下,addAll()操作——将所有这 3 个元素添加到底层 Collection 中并没有执行addAll()应该返回 false。但是,前 2 个元素是存在的——开发人员会期望它们不应该是(?)

HashSet在其 Collection 类型的带有单参数的构造函数中使用了这个addAll() 。

因此,开发人员在寻找整个集合时,最终可能会得到一个包含他集合的一部分的HashSet实例。这发生在没有任何警告的情况下。

所涉及的方法 ——HashMapput()HashSet的add()看起来很简单——在这些操作期间似乎没有任何问题——但仍然如此。

我在这里错过了什么吗?

4

5 回答 5

6

的合同Collection#addAll(...)只是说true如果集合(this)被修改,它会返回。它不保证添加将是原子的或完整的。

于 2013-07-31T23:18:26.370 回答
5

在这种 [不是所有元素都被添加] 的情况下,addAll() 操作——将所有这 3 个元素添加到基础 Collection 中并没有执行 addAll() 应该返回 false。

addAll()true如果的任何元素c已成功添加,则返回,而不是全部添加。您可以从您发布的代码中看到这一点:modified设置为true as soon as a add()call return true

于 2013-07-31T23:19:50.583 回答
3

正如其他人已经提到的,true如果成功添加了任何元素,则该方法返回。

另外: http://docs.oracle.com/javase/6/docs/api/java/util/Collection.html#add(E)

如果一个集合拒绝添加一个特定元素,除了它已经包含该元素之外,它必须抛出一个异常(而不是返回 false)。这保留了在此调用返回后集合始终包含指定元素的不变量。

因此,鉴于addAll您介绍的实现,如果没有添加元素,并且没有引发异常,那是因为该元素已经在集合中。

于 2013-07-31T23:28:28.067 回答
2

HashSet因此,开发人员在寻找整个集合时,最终可能会得到一个包含他集合的一部分的实例。这发生在没有任何警告的情况下。

不对。Set.add返回的事实false意味着它已经存在。唯一的例外是有大小限制的有界集合,此时开发人员应该知道它无论如何都是有界集合并且不一定包含所有元素。对于集合 API 中的大多数集合,如果您使用相同的集合调用它,调用addAll保证containsAll将返回。true即这将打印true

Set<T> set1 = new HashSet<>();
Set<T> set2 = new HashSet<>();
// Add stuff to the sets
set1.addAll(set2);
System.out.println(set1.containsAll(set2));
于 2013-07-31T23:27:18.343 回答
1

javadoc说如果当前被修改则addAll返回(否则)。trueCollectionfalse

这意味着即使只添加了一个元素,该方法也会返回true. 将返回值视为该集合是否因方法调用而被修改的指标,而不是所有元素都已添加的指标。

于 2013-07-31T23:19:21.617 回答