Risposte:
Meglio usare una libreria come Guava :
import com.google.common.collect.Lists;
Iterator<Element> myIterator = ... //some iterator
List<Element> myList = Lists.newArrayList(myIterator);
Un altro esempio di Guava:
ImmutableList.copyOf(myIterator);
import org.apache.commons.collections.IteratorUtils;
Iterator<Element> myIterator = ...//some iterator
List<Element> myList = IteratorUtils.toList(myIterator);
In Java 8, è possibile utilizzare il nuovo forEachRemainingmetodo che è stato aggiunto Iteratorall'interfaccia:
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
::? che nome ha? sembra un riferimento diretto a list.add (); e sembra anche qualcosa di nuovo di java8; e grazie! :)
::sintassi è nuova in Java 8 e si riferisce a un "metodo di riferimento", che è una forma abbreviata di un lambda. Vedi qui per ulteriori informazioni: docs.oracle.com/javase/tutorial/java/javaOO/…
iterator? è un simbolo irrisolto
iterator.
Puoi copiare un iteratore in un nuovo elenco come questo:
Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
copy.add(iter.next());
Ciò presuppone che l'elenco contenga stringhe. Non c'è davvero un modo più veloce per ricreare un elenco da un iteratore, sei bloccato nel attraversarlo a mano e copiare ogni elemento in un nuovo elenco del tipo appropriato.
MODIFICARE :
Ecco un metodo generico per copiare un iteratore in un nuovo elenco in modo sicuro:
public static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Usalo in questo modo:
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]
Nota che c'è una differenza tra Iterablee Iterator.
Se ne hai uno Iterable, allora con Java 8 puoi usare questa soluzione:
Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
Come so Collectors.toList()crea ArrayLististanza.
In realtà a mio avviso, sembra anche buono in una riga.
Ad esempio se è necessario tornare List<Element>da un metodo:
return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());
Iterable iterator. Sono completamente diversi.
Iteratornuovo ad un singolo uso Iterable utilizzando () -> iterator. Questo può essere utile in situazioni come questa, ma vorrei sottolineare ancora una volta la cosa importante: puoi usare questo metodo solo se monouso Iterable è accettabile. Chiamare iterable.iterator()più di una volta produrrà risultati inaspettati. La risposta di cui sopra diventa quindiIterator<Element> iterator = createIterator(); List<Element> array = StreamSupport.stream(((Iterable<Element>) () -> iterable).spliterator(), false).collect(toList());
Puoi anche usare IteratorUtilsda commons-collection di Apache , sebbene non supporti generici:
List list = IteratorUtils.toList(iterator);
Soluzione piuttosto concisa con Java 8 semplice usando 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 ), anche nuovo in Java 8, è molto più conciso. L'inserimento della variabile elenco in Collectornon migliora la leggibilità in questo caso, poiché deve essere supportato da a Streame a Spliterator.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Prova StickyListda Cactoos :
List<String> list = new StickyList<>(iterable);
Disclaimer: sono uno degli sviluppatori.
Iterable! =Iterator
Voglio solo sottolineare una soluzione apparentemente ovvia che NON funzionerà:
Elenco elenco = Stream.generate (iteratore :: successivo) .Raccogliere (Collectors.toList ());
Questo perché Stream#generate(Supplier<T>)può creare solo flussi infiniti, non si aspetta che il suo argomento venga lanciato NoSuchElementException(questo è ciò Iterator#next()che farà alla fine).
La risposta di xehpuk dovrebbe essere usata invece se il modo Iteratore → Stream → Elenco è la tua scelta.
usa google guava !
Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);
++
Qui in questo caso, se si desidera il modo più veloce possibile, allora for loopè meglio.
L'iteratore su una dimensione del campione di 10,000 runstake prende 40 mscome per loop2 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));
Ciò presuppone che l'elenco contenga stringhe.
for loop e accedere agli elementi di una lista get(i)è più veloce dell'uso di un iteratore ... ma non è quello che l'OP stava chiedendo, ha specificamente menzionato che un iteratore è dato come input.
get(int)loop stai guardando solo 100k delle voci da 1m. Se cambi quel loop per essere it.size()vedrai che questi 2 metodi sono vicini alla stessa velocità. In generale, questi tipi di test di velocità Java forniscono informazioni limitate sulle prestazioni della vita reale e dovrebbero essere considerati scettici.