264

给定Iterator<Element>,我们如何方便地将其转换Iterator为 a List<Element>,以便我们可以List在其上使用 ' 操作,例如get(index),add(element)等。

4

12 回答 12

383

更好地使用像Guava这样的库:

import com.google.common.collect.Lists;

Iterator<Element> myIterator = ... //some iterator
List<Element> myList = Lists.newArrayList(myIterator);

另一个番石榴示例:

ImmutableList.copyOf(myIterator);

Apache Commons 集合

import org.apache.commons.collections.IteratorUtils;

Iterator<Element> myIterator = ...//some iterator

List<Element> myList = IteratorUtils.toList(myIterator);       
于 2012-06-11T06:34:08.740 回答
268

在 Java 8 中,您可以使用forEachRemaining已添加到Iterator接口的新方法:

List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
于 2015-02-13T02:54:08.893 回答
69

您可以像这样将迭代器复制到新列表中:

Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
    copy.add(iter.next());

这是假设列表包含字符串。从迭代器重新创建列表确实没有更快的方法,您不得不手动遍历它并将每个元素复制到适当类型的新列表中。

编辑 :

这是一种以类型安全的方式将迭代器复制到新列表的通用方法:

public static <T> List<T> copyIterator(Iterator<T> iter) {
    List<T> copy = new ArrayList<T>();
    while (iter.hasNext())
        copy.add(iter.next());
    return copy;
}

像这样使用它:

List<String> list = Arrays.asList("1", "2", "3");
Iterator<String> iter = list.iterator();
List<String> copy = copyIterator(iter);
System.out.println(copy);
> [1, 2, 3]
于 2012-04-12T03:36:03.360 回答
29

Iterable注意和之间有区别Iterator

如果您有Iterable,那么对于 Java 8,您可以使用以下解决方案:

Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
    .stream(iterable.spliterator(), false)
    .collect(Collectors.toList());

据我所知,Collectors.toList()创建ArrayList实例。

实际上在我看来,它在一行中也看起来不错。
例如,如果您需要List<Element>从某个方法返回:

return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());
于 2016-12-29T18:44:04.580 回答
24

您也可以IteratorUtils从 Apache commons-collections使用,尽管它不支持泛型:

List list = IteratorUtils.toList(iterator);
于 2013-03-20T06:59:39.203 回答
10

使用纯 Java 8 的非常简洁的解决方案java.util.stream

public static <T> ArrayList<T> toArrayList(final Iterator<T> iterator) {
    return StreamSupport
        .stream(
            Spliterators
                .spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
        .collect(
                Collectors.toCollection(ArrayList::new)
    );
}
于 2014-06-02T15:15:00.583 回答
6

在没有外部依赖的情况下,这是一个使用 Streams 和 java 16 toList() 的单线器。

给定一个Iterator<?> iterator

List<?> list = StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false).toList();
于 2020-05-15T14:39:07.893 回答
5
List result = new ArrayList();
while (i.hasNext()){
    result.add(i.next());
}
于 2012-04-12T03:36:53.247 回答
1

StickyListCactoos尝试:

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

免责声明:我是开发人员之一。

于 2017-06-20T17:36:55.923 回答
1

我只想指出一个看似显而易见但行不通的解决方案

列表列表 = Stream.generate(iterator::next)
    .collect(Collectors.toList());

那是因为Stream#generate(Supplier<T>)只能创建无限流,它不希望它的参数抛出NoSuchElementException(这就是Iterator#next()最终会做的事情)。

如果您选择 Iterator→Stream→List 方式,则应使用xehpuk 的答案。

于 2017-10-20T02:24:30.580 回答
0

使用谷歌番石榴

Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);

++

于 2012-10-08T17:11:23.787 回答
-2

在这种情况下,如果您想要尽可能快的方式,那就for loop更好了。

迭代样本大小的迭代器,10,000 runs其中40 msfor 循环需要2 ms

        ArrayList<String> alist = new ArrayList<String>();  
        long start, end;  

        for (int i = 0; i < 1000000; i++) {  
            alist.add(String.valueOf(i));  
        }  

        ListIterator<String> it = alist.listIterator();      

        start = System.currentTimeMillis();  
        while (it.hasNext()) {  
            String s = it.next();  
        }  
        end = System.currentTimeMillis();  

        System.out.println("Iterator start: " + start + ", end: " + end + ", delta: "  
            + (end - start));  
        start = System.currentTimeMillis();  
        int ixx = 0;  
        for (int i = 0; i < 100000; i++) {  
            String s = alist.get(i);  
        }  

        System.out.println(ixx);  
        end = System.currentTimeMillis();  
        System.out.println("for loop start: " + start + ", end: " + end + ", delta: "  
            + (end - start));  

这是假设列表包含字符串。

于 2012-04-12T03:48:44.307 回答