关于Java:将迭代转换为集合的简单方法

Easy way to convert Iterable to Collection

在我的应用程序中,我使用第三方库(MongoDB的Spring数据是准确的)。

这个库的方法返回Iterable,而我的其余代码则期望Collection

有什么实用方法可以让我快速地将一个转换成另一个吗?我希望避免在我的代码中为这样一个简单的事情创建一组foreach循环。


用Guava你可以使用Lists.Newarraylist(Iterable)或sets.Newhashset(Iterable),among other similar methods.这将把所有元素复制到记忆中。如果不能接受的话,我想你的代码是用这些代码来代替IterableRather than Collection。Guava also happens to provide convenient methods for doing things you can do on a Collectionusing an Iterable(such as Iterables.isEmpty(Iterable)or EDOCX1〕16〕,but the performance implications are more obvious.


In JDK 8,without depending on additional libs:

1
2
3
Iterator<T> source = ...;
List<T> target = new ArrayList<>();
source.forEachRemaining(target::add);

上一篇是为Iterator而写的。如果你和Iterable

1
iterable.forEach(target::add);


你可以为这个写你自己的使用方法:

1
2
3
4
5
6
7
public static <E> Collection<E> makeCollection(Iterable<E> iter) {
    Collection<E> list = new ArrayList<E>();
    for (E item : iter) {
        list.add(item);
    }
    return list;
}


简明溶液与爪哇8使用java.util.stream

1
2
3
4
public static <T> List<T> toList(final Iterable<T> iterable) {
    return StreamSupport.stream(iterable.spliterator(), false)
                        .collect(Collectors.toList());
}


5.May help(although they don't support generics in the latest stable version 3.2.1):

1
2
@SuppressWarnings("unchecked")
Collection<Type> list = IteratorUtils.toList(iterable.iterator());

版本4.0(此时此刻在抽屉里)的一般材料,您可以从EDOCX1中找到〔19〕。

最新资料:CACTOOOS


From collections:

1
2
List<T> targetCollection = new ArrayList<T>();
CollectionUtils.addAll(targetCollection, iterable.iterator())

There are the full sources of this utility method:

ZZU1


不要忘记所有的收藏都结束了,而不能忘记所有的承诺。如果你能得到一个项目,那就是它。

1
2
3
for (piece : sthIterable){
..........
}

Will be expanded to:

1
2
3
4
5
Iterator it = sthIterable.iterator();
while (it.hasNext()){
    piece = it.next();
..........
}

It.hasnext()is not required to ever return false.在一般情况下,你不希望能够将每一个项目都转换为一个收藏。例如,你可以在所有正数上重复,在某些循环中重复,在这些循环中产生同样的结果,并且再次产生同样的结果,等等。

其他:Atrey的回答很好。


我使用EDOCX1


这不是回答你的问题,但我相信这是解决你问题的办法。但你不应该使用这个界面。Instead use sub interfaces,in your case org.springframework.data.mongodb.repository.MongoRepository该界面的方法是返回java.util.List型物体。


如果可以的话,我会使用我的习惯用法来编辑一个现有的收藏。

手:

1
2
3
4
5
6
7
public static <T> Collection<T> toCollection(Iterable<T> iterable) {
    if (iterable instanceof Collection) {
        return (Collection<T>) iterable;
    } else {
        return Lists.newArrayList(iterable);
    }
}

理想的是,上面的文献将使用不可更改的文献,但不可更改的文献不允许任何可能产生不受欢迎的结果的文献。

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@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));
}

I implement similar utilities for all subtypes of collections(set,list,etc).我想这些都是瓜瓦的一部分,但我找不到。


当你叫containscontainsAllequalshashCoderemove,EDOCX1〕,retainAllsize,或toArray时,你必须穿过任何一条道路。

如果你只是偶然的呼唤方法,如isEmptyclear,我想你最好创作Lazily系列。你可以用ArrayList来保存预编辑的元素。

我不知道在任何图书馆里有这么一类的人,但这应该是一个简单的练习来写作。


In Java 8,you can do this to add all elements from an Iterableto Collectionand return it:

1
2
3
4
5
public static <T> Collection<T> iterableToCollection(Iterable<T> iterable) {
  Collection<T> collection = new ArrayList<>();
  iterable.forEach(collection::add);
  return collection;
}

Informed by@afreys answer.


自从Rxjava是一个汉默,而这个金达看起来像个侏儒,你可以做到。

1
Observable.from(iterable).toList().toBlocking().single();


这里有一个SSCCE,用于在Java 8中实现这一点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class IterableToCollection {
    public interface CollectionFactory <T, U extends Collection<T>> {
        U createCollection();
    }

    public static <T, U extends Collection<T>> U collect(Iterable<T> iterable, CollectionFactory<T, U> factory) {
        U collection = factory.createCollection();
        iterable.forEach(collection::add);
        return collection;
    }

    public static void main(String[] args) {
        Iterable<Integer> iterable = IntStream.range(0, 5).boxed().collect(Collectors.toList());
        ArrayList<Integer> arrayList = collect(iterable, ArrayList::new);
        HashSet<Integer> hashSet = collect(iterable, HashSet::new);
        LinkedList<Integer> linkedList = collect(iterable, LinkedList::new);
    }
}

两个剩余

  • 没有必要转换为收藏使用预览可直接在这种环路中使用,没有语法上的不同,所以我很难理解为什么原来的问题是问的。
  • 建议以不安全的方式转换到收藏(与收藏相同)——没有任何保障,因此没有任何保障,致使下一个()方法返回不同的对象实例。此外,这不是一个纯粹的理论问题。E.g.Iterable implementation used to pass values to a reduce method of hadoop reducer always returns the same value instance,just with different field values.如果你从上面应用程序(或收藏工具.Addall(Iterator))的话,你会以所有相同的元素完成收藏。

  • 试试Cactoos的StickyList

    1
    List<String> list = new StickyList<>(iterable);