将Iterator转换为ArrayList

给定Iterator<Element> ,我们如何以尽可能最快和最快的方式将该迭代器转换为ArrayList<Element> (或List<Element> ),以便我们可以使用ArrayList的操作,比如get(index) add(element)

最好使用像番石榴一样的图书馆:

 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); 

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

 List<Element> list = new ArrayList<>(); iterator.forEachRemaining(list::add); 

你可以像下面这样将一个迭代器复制到一个新的列表中:

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

这是假设列表包含string。 实际上没有更快的方式来从一个迭代器重新创build一个列表,你坚持手动遍历它,并将每个元素复制到一个新的适当types的列表。

编辑:

下面是一个以types安全的方式将迭代器复制到新列表的通用方法:

 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] 

您也可以使用Apache commons-collections中的 IteratorUtils ,尽pipe它不支持generics:

 List list = IteratorUtils.toList(iterator); 

用java 8你可以使用这个解决scheme:

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

据我所知Collectors.toList()创buildArrayList实例。

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

 return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList()); 
 List result = new ArrayList(); while (i.hasNext()){ result.add(i.next()); } 

使用java.util.stream简单Java 8相当简洁的解决scheme:

 public static <T> ArrayList<T> toArrayList(final Iterator<T> iterator) { return StreamSupport .stream( Spliterators .spliteratorUnknownSize(iterator, Spliterator.ORDERED), false) .collect( Collectors.toCollection(ArrayList::new) ); } 

使用谷歌番石榴 !

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

++

从Cactoos尝试StickyList :

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

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

我只想指出一个看起来很明显的解决scheme,它不起作用:

 List list = Stream.generate(iterator :: next) 
      .collect(Collectors.toList());

这是因为Stream#generate(Supplier<T>)只能创build无限的stream,所以它不会指望它的参数抛出NoSuchElementException (这就是Iterator#next()会做的)。

如果迭代器→stream→列表方式是您的select,则应该使用xehpuk的答案 。

这里可以使用Iterator中的Java 8 forEachRemaining方法:

 List<Element> elementList = new ArrayList<>(); iterator.forEachRemaining(elementList::add); 

在这种情况下,如果你想要最快的方式,那么for loop更好。

对于10,000 runs的样本大小,迭代器需要40 ms ,for循环需要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)); 

这是假设列表包含string。