Java: 为什么Collection.addAll不能接受Iterables?

45
我想知道为什么Collection.addAll()方法只接受其他Collection而不是Iterable。这是为什么呢?
是否有类似的方法可以用于Iterable

如果您正在寻找一种在没有显式循环的情况下向集合添加迭代器的最简单方法,那么您可以使用yourCollection.addAll(org.apache.commons.collections.IteratorUtils.toList(yourIterable.iterator())) - mihi
1
如果您的Iterable是一个数组,请使用java.util.Arrays.asList() - mihi
1
数组不实现 Iterable - Steve Kuo
@SteveKuo:您能详细说明一下与问题相关的含义吗? - O. R. Mapper
5个回答

39

可能是因为Java 1.2引入了Collection接口,而Iterable直到1.5才出现,更改接口将会破坏所有现有的实现。


4
这并没有解释为什么随后没有添加该方法。 - user48956
@user48956:是的,它确实会:“更改接口将破坏所有现有的实现”。不过随着Java 8中默认方法的引入,这实际上变得不再正确。 - Michael Borgwardt
因为在添加Iterable时,可以将addAll(Iterable)添加到addAll(Collection)中。那么它没有被添加的原因是什么? - user48956
他们本可以在Java 5中为"可迭代对象"和"迭代器"添加一个Collections.addAll(coll, it)方法,同时在Collection#addAll上加上一个@see。虽然它不能很聪明地进行参数下转换,但我相信大多数解决方法也没有这样做。 - TWiStErRob
2
这并没有解释为什么它没有作为Java 8中的默认方法添加。我倾向于@OscarRyz的答案,认为这与“Collection”表示有限元素集有关。 - shmosel
显示剩余4条评论

35

5
当有疑问时,始终检查Guava是一个不错的选择。大多数Apache Commons库都很棒,但是Commons/Collections很烦人,因为它不支持泛型。 - Sean Patrick Floyd
它有一个支持泛型的分支:https://github.com/megamattron/collections-generic - thSoft
损坏的链接。现在是http://commons.apache.org/proper/commons-collections/javadocs/api-release/index.html。 - Ian

13

其他人已经详细回答了“为什么”的问题。

有没有类似的方法可以用于迭代器?

在Java 8中,你不再需要使用addAll

Collection<X> coll = ...;
Iterable<X> it = ...;
it.forEach(coll::add); // coll.addAll(it);

这正是我一直在寻找的。只用JDK就可以实现,真是太感谢了! - Michael
如果该流是并行流,那么这是否有效? 那么您将同时调用 coll.add - Jens
有人对此进行过基准测试吗?它的速度是否相当快? - kap
这不是一个好的解决方案,因为它使可迭代对象负责迭代。你放弃了如何执行迭代的控制权。使用addAll方法,你只需请求源提供迭代器即可。但如果使用可重写的forEach方法,你无法控制迭代方式。因此,你无法做出与性能相关的任何估计。 - RedCrafter LP

11

基本上因为Iterable可能永远不会结束(也就是说,hasNext()会永远返回true)。

此外,为了保持一致性,您可能认为Collection可以添加另一个集合的所有元素,但是,Iterable并不一定是一个集合(它可以是任何东西,比如ResultSet包装器)。


啊,你的第一个观点很好。我不太明白你在第二个观点中的意思,以及它如何影响addAll方法。 - Albert
至于第二个问题,可迭代对象是一种接口,几乎任何东西都可以实现它,你可能会陷入第一个情况,出现可能无限循环的情况。 - OscarRyz
6
我不确定是否同意。一个集合可以像可迭代对象一样是无限的,因为你可以构建一个有效的集合作为可迭代对象的包装器。 - GaryF
4
没关系,我已经查看了文档,http://download.oracle.com/javase/6/docs/api/java/util/Collection.html#size%28%29 应该返回Integer.MAX_VALUE。 - OscarRyz
@GaryF 我认为集合不应该是无限的,否则 removeAll()retainAll() 可能会无限执行。@OscarRyz 仅仅因为大小可能大于 Integer.MAX_VALUE 并不意味着它可以是无限的。而且接口甚至不能正确支持大于 Integer.MAX_VALUE 的集合,因为 toArray() 承诺返回所有元素,即使数组不能大于 Integer.MAX_VALUE - shmosel

3

在核心JDK中,有很多东西与普通的可迭代对象不太兼容。我建议使用Guava来克服这些缺点。


你好,能否简要列出一些这些缺点? - ctomek
@ctomek:实际上,这将是Guava提供的列表,最好通过跟随链接并查看其提供的内容来展示... - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接