Ответы:
Лучше использовать такую библиотеку, как 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);
В Java 8 вы можете использовать новый forEachRemaining
метод, который был добавлен в Iterator
интерфейс:
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
::
? какое имя у него есть? кажется прямой ссылкой на list.add (); и кажется также некоторая новая вещь java8; и спасибо! :)
::
Синтаксис является новым в Java 8, и он ссылается на «ссылку на метод», которая является сокращенной формой лямбды. Смотрите здесь для получения дополнительной информации: docs.oracle.com/javase/tutorial/java/javaOO/…
iterator
идет? это неразрешенный символ
iterator
.
Вы можете скопировать итератор в новый список, например так:
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]
Обратите внимание, что есть разница между 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());
Iterable
iterator
. Они совершенно разные.
Iterator
обратно в одно использование Iterable
с помощью () -> iterator
. Это может быть полезно в подобных ситуациях, но позвольте мне еще раз подчеркнуть важную вещь: вы можете использовать этот метод, только если допустимо одноразовое использование Iterable
. Звонок iterable.iterator()
более одного раза даст неожиданные результаты. Выше ответ становитсяIterator<Element> iterator = createIterator();
List<Element> array = StreamSupport.stream(((Iterable<Element>) () -> iterable).spliterator(), false).collect(toList());
Вы также можете использовать IteratorUtils
из Apache commons-collection , хотя он не поддерживает дженерики:
List list = IteratorUtils.toList(iterator);
Довольно краткое решение с простой 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)
);
}
iterator.forEachRemaining( list::add )
, также новый в Java 8, гораздо более кратким. Collector
Вставка переменной списка в не улучшает читаемость в этом случае, так как она должна поддерживаться a Stream
и a Spliterator
.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Попробуйте StickyList
от Cactoos :
List<String> list = new StickyList<>(iterable);
Отказ от ответственности: я один из разработчиков.
Iterable
! =Iterator
Я просто хочу указать на кажущееся очевидным решение, которое НЕ будет работать:
Список список = Stream.generate (итератор :: следующий) .collect (Collectors.toList ());
Это потому, что Stream#generate(Supplier<T>)
может создавать только бесконечные потоки, он не ожидает, что его аргумент будет выдан NoSuchElementException
(это то, что Iterator#next()
будет делать в конце).
Вместо этого следует использовать ответ xehpuk, если вы выбрали путь Iterator → Stream → List.
использовать гугл гуава !
Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);
++
Вот в этом случае, если вы хотите самый быстрый путь, то 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));
Это при условии, что список содержит строки.
for
цикла и доступ к элементам списка get(i)
быстрее, чем использование итератора ... но это не то, о чем спрашивал ОП, он специально упомянул, что в качестве входных данных указан итератор .
get(int)
цикле вы просматриваете только 100 тыс. Записей из 1 млн. Если вы измените этот цикл, it.size()
вы увидите, что эти 2 метода близки к одинаковой скорости. В целом, такие тесты скорости Java предоставляют ограниченную информацию о производительности в реальной жизни и должны рассматриваться скептически.