java list iterable_java - 将Iterable转换为Collection的简便方法

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值