Відповіді:
Краще використовувати бібліотеку на зразок 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 забезпечують обмежену реальну інформацію про продуктивність, і їх слід розглядати скептично.