Преобразование итератора в 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);
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)
);
}
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));
это предполагает, что список содержит строки.