在我的应用程序中,我使用第三方库(Spring Data for MongoDB准确地说)。
这个库的方法返回Iterable<T>,而我的其余代码期望Collection<T>。
有没有什么实用的方法可以让我快速地把一个转换成另一个?为了这么简单的事情,我希望避免在代码中创建一堆foreach循环。
在我的应用程序中,我使用第三方库(Spring Data for MongoDB准确地说)。
这个库的方法返回Iterable<T>,而我的其余代码期望Collection<T>。
有没有什么实用的方法可以让我快速地把一个转换成另一个?为了这么简单的事情,我希望避免在代码中创建一堆foreach循环。
当前回答
Java 8使用Java .util.stream的简洁解决方案:
public static <T> List<T> toList(final Iterable<T> iterable) {
return StreamSupport.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
}
从Java 16开始,你可以使用Stream.toList():
public static <T> List<T> toList(final Iterable<T> iterable) {
return StreamSupport.stream(iterable.spliterator(), false)
.toList();
}
其他回答
尽管如此,不要忘记所有的集合都是有限的,而Iterable没有任何承诺。如果某个东西是Iterable,你可以得到一个Iterator,就是这样。
for (piece : sthIterable){
..........
}
将扩大到:
Iterator it = sthIterable.iterator();
while (it.hasNext()){
piece = it.next();
..........
}
it.hasNext()不需要返回false。因此,在一般情况下,您不能期望能够将每个Iterable转换为一个集合。例如,你可以遍历所有正自然数,遍历带有循环的东西,反复产生相同的结果,等等。
除此之外:Atrey的回答很好。
来自common -collections的IteratorUtils可能会有所帮助(尽管它们在最新的稳定版本3.2.1中不支持泛型):
@SuppressWarnings("unchecked")
Collection<Type> list = IteratorUtils.toList(iterable.iterator());
4.0版本(目前在SNAPSHOT中)支持泛型,您可以去掉@SuppressWarnings。
更新:检查IterableAsList从仙人掌。
因为RxJava是一个锤子,而这个看起来像钉子,你可以这样做
Observable.from(iterable).toList().toBlocking().single();
我使用我的自定义实用程序强制转换现有的集合(如果可用)。
主要:
public static <T> Collection<T> toCollection(Iterable<T> iterable) {
if (iterable instanceof Collection) {
return (Collection<T>) iterable;
} else {
return Lists.newArrayList(iterable);
}
}
理想情况下,上面将使用immutabelist,但ImmutableCollection不允许空值,这可能会产生不希望看到的结果。
测试:
@Test
public void testToCollectionAlreadyCollection() {
ArrayList<String> list = Lists.newArrayList(FIRST, MIDDLE, LAST);
assertSame("no need to change, just cast", list, toCollection(list));
}
@Test
public void testIterableToCollection() {
final ArrayList<String> expected = Lists.newArrayList(FIRST, null, MIDDLE, LAST);
Collection<String> collection = toCollection(new Iterable<String>() {
@Override
public Iterator<String> iterator() {
return expected.iterator();
}
});
assertNotSame("a new list must have been created", expected, collection);
assertTrue(expected + " != " + collection, CollectionUtils.isEqualCollection(expected, collection));
}
我为集合的所有子类型(Set,List等)实现了类似的实用程序。我以为这些已经是番石榴的一部分了,但我还没找到。
只要你调用contains, containsAll, equals, hashCode, remove, retainAll, size或toArray,你就必须遍历元素。
如果您偶尔只调用isEmpty或clear等方法,我认为您最好是惰性地创建集合。例如,你可以有一个支持数组列表来存储先前迭代的元素。
我不知道任何一个库中有这样的类,但是编写它应该是一个相当简单的练习。