java - 将Iterable转换为Collection的简便方法
在我的应用程序中,我使用第三方库(确切地说是MongoDB的Spring Data)。
此库的方法返回foreach,而我的其余代码需要Collection。
有什么实用方法可以让我快速将一个转换为另一个吗? 我想避免在我的代码中为这么简单的事情创建一堆foreach循环。
Ula Krukar asked 2019-01-30T04:52:18Z
16个解决方案
332 votes
使用Guava,您可以使用Lists.newArrayList(Iterable)或Sets.newHashSet(Iterable)以及其他类似的方法。 这当然会将所有元素复制到内存中。 如果这是不可接受的,我认为你的代码应该采用Iterable而不是Collection.番石榴也恰好提供了方便的方法,可以使用Iterable(例如Iterables.isEmpty(Iterable)或Iterables.contains(Iterable, Object))在Collection上进行操作, 但性能影响更明显。
ColinD answered 2019-01-30T04:52:26Z
255 votes
在JDK 8中,不依赖于其他库:
Iteratorsource=...;Listtarget=newArrayList<>();source.forEachRemaining(target::add);
编辑:以上是Iterator.如果您正在处理Iterable,
iterable.forEach(target::add);
Thamme Gowda answered 2019-01-30T04:52:56Z
81 votes
您也可以为此编写自己的实用程序方法:
publicstaticCollectionmakeCollection(Iterableiter){Collectionlist=newArrayList();for(E item:iter){list.add(item);}returnlist;}
Atreys answered 2019-01-30T04:53:18Z
59 votes
Java 8使用java.util.stream的简明解决方案:
publicstaticListtoList(finalIterableiterable){returnStreamSupport.stream(iterable.spliterator(),false).collect(Collectors.toList());}
xehpuk answered 2019-01-30T04:53:41Z
40 votes
IterableAsList自IterableAsList可能有所帮助(尽管它们不支持最新稳定版本3.2.1中的泛型):
@SuppressWarnings("unchecked")Collectionlist=IteratorUtils.toList(iterable.iterator());
版本4.0(此时在SNAPSHOT中)支持泛型,您可以摆脱IterableAsList。
更新:从Cactoos检查IterableAsList。
yegor256 answered 2019-01-30T04:54:17Z
19 votes
来自CollectionUtils:
ListtargetCollection=newArrayList();CollectionUtils.addAll(targetCollection,iterable.iterator())
以下是此实用程序方法的完整来源:
publicstaticvoidaddAll(Collectioncollection,Iteratoriterator){while(iterator.hasNext()){collection.add(iterator.next());}}
Tomasz Nurkiewicz answered 2019-01-30T04:54:46Z
14 votes
在此期间,不要忘记所有集合都是有限的,而Iterable没有任何承诺。 如果某些东西是Iterable,你可以得到一个Iterator,就是这样。
for(piece:sthIterable){..........}
将扩大到:
Iteratorit=sthIterable.iterator();while(it.hasNext()){piece=it.next();..........}
it.hasNext()不需要返回false。 因此,在一般情况下,您不能期望能够将每个Iterable转换为Collection。 例如,你可以迭代所有正数自然数,迭代一些带有循环的东西,一遍又一遍地产生相同的结果,等等。
否则:Atrey的答案很好。
Alexander Shopov answered 2019-01-30T04:55:28Z
13 votes
我经常使用FluentIterable.from(myIterable).toList()。
fringd answered 2019-01-30T04:55:50Z
7 votes
这不是您问题的答案,但我相信这是您问题的解决方案。 接口org.springframework.data.repository.CrudRepository确实具有返回java.lang.Iterable的方法,但您不应使用此接口。 而是使用子接口,在您的情况下为org.springframework.data.mongodb.repository.MongoRepository.此接口具有返回类型为java.util.List的对象的方法。
Ludwig Magnusson answered 2019-01-30T04:56:13Z
6 votes
我使用自定义实用程序来转换现有的Collection(如果可用)。
主要:
publicstaticCollectiontoCollection(Iterableiterable){if(iterableinstanceofCollection){return(Collection)iterable;}else{returnLists.newArrayList(iterable);}}
理想情况下,上面将使用ImmutableList,但ImmutableCollection不允许可能提供不良结果的空值。
测试:
@TestpublicvoidtestToCollectionAlreadyCollection(){ArrayListlist=Lists.newArrayList(FIRST,MIDDLE,LAST);assertSame("no need to change, just cast",list,toCollection(list));}@TestpublicvoidtestIterableToCollection(){finalArrayListexpected=Lists.newArrayList(FIRST,null,MIDDLE,LAST);Collectioncollection=toCollection(newIterable(){@OverridepublicIteratoriterator(){returnexpected.iterator();}});assertNotSame("a new list must have been created",expected,collection);assertTrue(expected+" != "+collection,CollectionUtils.isEqualCollection(expected,collection));}
我为集合的所有子类型(Set,List等)实现了类似的实用程序。 我认为这些已经成为番石榴的一部分,但我还没有找到它。
Aaron Roller answered 2019-01-30T04:56:53Z
5 votes
只要您致电isEmpty,clear,2199511553776616450,2199511553776616451,2199511553776616452,2199511553776616453,size或toArray,您就必须无论如何都要遍历这些元素。
如果你偶尔只调用isEmpty或clear这样的方法,我想你最好通过懒惰地创建集合。 例如,您可以使用后备ArrayList来存储以前迭代的元素。
我不知道任何图书馆里有这样的课程,但写起来应该是一个相当简单的练习。
aioobe answered 2019-01-30T04:57:30Z
4 votes
在Java 8中,您可以执行此操作以将所有元素从Iterable添加到Collection并将其返回:
publicstaticCollectioniterableToCollection(Iterableiterable){Collectioncollection=newArrayList<>();iterable.forEach(collection::add);returncollection;}
灵感来自@Afreys的回答。
answered 2019-01-30T04:57:58Z
4 votes
既然RxJava是锤子,这种看起来像钉子,你可以做到
Observable.from(iterable).toList().toBlocking().single();
DariusL answered 2019-01-30T04:58:21Z
3 votes
这是一个SSCCE,可以在Java 8中实现这一目标
importjava.util.ArrayList;importjava.util.Collection;importjava.util.HashSet;importjava.util.LinkedList;importjava.util.stream.Collectors;importjava.util.stream.IntStream;publicclassIterableToCollection{publicinterfaceCollectionFactory>{U createCollection();}publicstatic>U collect(Iterableiterable,CollectionFactoryfactory){U collection=factory.createCollection();iterable.forEach(collection::add);returncollection;}publicstaticvoidmain(String[]args){Iterableiterable=IntStream.range(0,5).boxed().collect(Collectors.toList());ArrayListarrayList=collect(iterable,ArrayList::new);HashSethashSet=collect(iterable,HashSet::new);LinkedListlinkedList=collect(iterable,LinkedList::new);}}
michaelsnowden answered 2019-01-30T04:58:43Z
2 votes
两个评论
没有必要将Iterable转换为Collection以使用foreachloop - Iterable可以直接在这样的循环中使用,没有语法差异,所以我几乎不明白为什么原来的问题被问到了。
将Iterable转换为Collection的建议方法是不安全的(与CollectionUtils相同) - 无法保证对next()方法的后续调用返回不同的对象实例。 而且,这种担忧并不是纯粹的理论。 例如。 用于将值传递给Hadoop Reducer的reduce方法的可执行实现始终返回相同的值实例,只是使用不同的字段值。 因此,如果您从上面应用makeCollection(或CollectionUtils.addAll(Iterator)),您将得到一个包含所有相同元素的集合。
al0 answered 2019-01-30T04:59:22Z
1 votes
从Cactoos尝试StickyList:
Listlist=newStickyList<>(iterable);
yegor256 answered 2019-01-30T04:59:44Z