[java] Преобразовать Iterator в ArrayList


Answers

В Java 8 вы можете использовать новый метод forEachRemaining который был добавлен в интерфейс Iterator :

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

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




Я просто хочу указать на очевидное решение, которое НЕ будет работать:

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

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

share следует использовать share если вы выбираете путь Iterator → Stream → List.




Здесь, в этом случае, если вам нужен самый быстрый способ, то 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));  

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




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



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

List list = IteratorUtils.toList(iterator);



Попробуйте StickyList из Cactoos :

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

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




Related