Відповіді:
Краще використовувати бібліотеку на зразок 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 , хоча він не підтримує дженерики:
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в цьому випадку не покращує читаність, оскільки вона повинна підтримуватися а Streamта a Spliterator.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Я просто хочу зазначити, здавалося б, очевидне рішення, яке НЕ буде працювати:
Список списків = Stream.generate (ітератор :: наступний) .collect (Collectors.toList ());
Це тому, що Stream#generate(Supplier<T>)може створювати лише нескінченні потоки, він не очікує, що його аргумент буде викинутий NoSuchElementException(ось що Iterator#next()буде зроблено в результаті).
Натомість слід використовувати відповідь xehpuk, якщо ваш вибір є ітератором → Потік → Список.
використовуйте google guava !
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 к 1m записів. Якщо ви зміните цю петлю, it.size()ви побачите, що ці два методи близькі до однакової швидкості. Загалом, такі випробування на швидкість на Java забезпечують обмежену реальну інформацію про продуктивність, і їх слід розглядати скептично.