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个元素添加到底层 收集不会被携带, addAll()正在返回false。但是,前两个元素是 - 和开发人员 会期望他们不应该是(?)
HashSet 在其构造函数中使用此 addAll(),其类型为Collection。
因此,开发人员最终可能会遇到 HashSet 实例 当他寻找整个系列时,它包含了他收藏的一部分。这没有任何警告就会发生。
所涉及的方法 - HashMap 的 put()和 HashSet 的 add()似乎很简单 - 在这些行动中似乎没有什么可以出错 - 但仍然如此。
我在这里错过了什么吗?
答案 0 :(得分:6)
Collection#addAll(...)
的合同仅表示如果修改了集合(this),则返回true
。它不保证添加是原子的还是完整的。
答案 1 :(得分:5)
在这个[并非所有被添加的元素]的情况下,addAll()操作 - 将所有这3个元素添加到基础Collection中,并且addAll()返回false应该是这样。
addAll()
如果成功添加了 true
的元素,则会返回c
,不是如果所有都添加了。您可以在发布的代码中看到这一点:modified
只要 add()
调用返回true
,就会设置为true
。
答案 2 :(得分:3)
正如其他人已经提到的,如果成功添加任何元素,该方法将返回true
。
此外: http://docs.oracle.com/javase/6/docs/api/java/util/Collection.html#add(E)
如果一个集合因为已经包含该元素的原因而拒绝添加特定元素,那么它必须抛出一个异常(而不是返回false)。这保留了在此调用返回后集合始终包含指定元素的不变量。
所以,考虑到你提出的addAll
的实现,如果没有添加元素,并且没有抛出异常,那是因为元素已经在集合中了。
答案 3 :(得分: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));
:
{{1}}
答案 4 :(得分:1)
javadoc表示addAll
如果修改了当前true
则返回Collection
,否则会false
。
这意味着即使只添加了一个元素,该方法也会返回true
。将返回值视为指示此集合是否由于方法调用而被修改而不是所有元素都已添加。