Преобразование итератора в ArrayList

дано Iterator<Element>, Как мы можем преобразовать это Iterator to ArrayList<Element> (или List<Element>) в лучший и быстрый возможный путь, так что мы можем использовать ArrayListоперации на нем, такие как get(index), add(element), etc.

12 ответов


лучше использовать библиотеку, как гуавы:

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, вы можете использовать новый тег forEachRemaining метод, который был добавлен к Iterator интерфейс:

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

это предполагает, что список содержит строки. На самом деле нет более быстрого способа воссоздать список из итератора, вы застряли с пересечением его вручную и копированием каждого элемента в новый список соответствующего типа.

EDIT:

вот общий метод копирования итератора в новый список безопасным для типа способом:

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]

вы также можете использовать IteratorUtils от Apache достояния-коллекции, хотя он не поддерживает дженерики:

List list = IteratorUtils.toList(iterator);

обратите внимание, что есть разница между 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());

довольно краткое решение с простой 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)
    );
}

List result = new ArrayList();
while (i.hasNext()){
    result.add(i.next());
}

Java 8 forEachRemaining метод в Iterator можно использовать здесь:

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

попробовать StickyList С Cactoos:

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

отказ от ответственности: я один из разработчиков.


используйте google гуавы !

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

++


Я просто хочу указать на кажущееся очевидным решение, которое не будет работы:

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

потому что Stream#generate(Supplier<T>) может создавать только бесконечные потоки, он не ожидает, что его аргумент бросит NoSuchElementException (это Iterator#next() сделаем в конце).

в xehpuk это следует использовать вместо этого, если ваш выбор-итератор→поток→список.


здесь в этом случае, если вы хотите самый быстрый способ, то for loop лучше.

итератор над размером выборки 10,000 runs принимает 40 ms где как за петлю берет 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));  

это предполагает, что список содержит строки.