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 forEachRemaining
metodo che è stato aggiunto Iterator
all'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 Iterable
e 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 ArrayList
istanza.
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.
Iterator
nuovo 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 IteratorUtils
da 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 Collector
non migliora la leggibilità in questo caso, poiché deve essere supportato da a Stream
e a Spliterator
.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Prova StickyList
da 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 runs
take prende 40 ms
come 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.