Antworten:
Verwenden Sie besser eine Bibliothek wie Guava :
import com.google.common.collect.Lists;
Iterator<Element> myIterator = ... //some iterator
List<Element> myList = Lists.newArrayList(myIterator);
Ein weiteres Guaven-Beispiel:
ImmutableList.copyOf(myIterator);
oder Apache Commons Sammlungen :
import org.apache.commons.collections.IteratorUtils;
Iterator<Element> myIterator = ...//some iterator
List<Element> myList = IteratorUtils.toList(myIterator);
In Java 8 können Sie die neue forEachRemaining
Methode verwenden, die der Iterator
Benutzeroberfläche hinzugefügt wurde :
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
::
? Welchen Namen hat es? scheint ein direkter Verweis auf list.add () zu sein; und scheint auch etwas Java8 Neues zu sein; und danke! :)
::
Syntax ist neu in Java 8 und bezieht sich auf eine "Methodenreferenz", bei der es sich um eine Kurzform eines Lambda handelt. Weitere Informationen finden Sie hier: docs.oracle.com/javase/tutorial/java/javaOO/…
iterator
das es ist ein ungelöstes Symbol
iterator
.
Sie können einen Iterator wie folgt in eine neue Liste kopieren:
Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
copy.add(iter.next());
Dies setzt voraus, dass die Liste Zeichenfolgen enthält. Es gibt wirklich keinen schnelleren Weg, eine Liste aus einem Iterator neu zu erstellen. Sie müssen sie nicht mehr manuell durchlaufen und jedes Element in eine neue Liste des entsprechenden Typs kopieren.
EDIT:
Hier ist eine generische Methode zum typsicheren Kopieren eines Iterators in eine neue Liste:
public static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Verwenden Sie es so:
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]
Beachten Sie, dass zwischen Iterable
und ein Unterschied besteht Iterator
.
Wenn Sie eine haben Iterable
, können Sie mit Java 8 diese Lösung verwenden:
Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
Wie ich weiß, Collectors.toList()
schafft ArrayList
Instanz.
Eigentlich sieht es meiner Meinung nach auch in einer Zeile gut aus.
Zum Beispiel, wenn Sie List<Element>
von einer Methode zurückkehren müssen:
return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());
Iterable
iterator
. Sie sind völlig anders.
Iterator
zurück zu einem einmaligen Gebrauch Iterable
durch Verwendung () -> iterator
. Dies kann in solchen Situationen nützlich sein, aber lassen Sie mich noch einmal das Wichtige betonen: Sie können diese Methode nur verwenden, wenn eine einmalige Verwendung Iterable
akzeptabel ist. Wenn Sie iterable.iterator()
mehr als einmal anrufen , erhalten Sie unerwartete Ergebnisse. Die obige Antwort wird dannIterator<Element> iterator = createIterator();
List<Element> array = StreamSupport.stream(((Iterable<Element>) () -> iterable).spliterator(), false).collect(toList());
Sie können auch IteratorUtils
aus Apache Commons-Sammlungen verwenden , obwohl es keine Generika unterstützt:
List list = IteratorUtils.toList(iterator);
Ziemlich prägnante Lösung mit einfachem Java 8 unter Verwendung von 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 )
, auch neu in Java 8, ist viel prägnanter. Das Collector
Verschieben der Listenvariablen in verbessert die Lesbarkeit in diesem Fall nicht, da sie von a Stream
und a unterstützt werden muss Spliterator
.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Versuchen StickyList
von Cactoos :
List<String> list = new StickyList<>(iterable);
Haftungsausschluss: Ich bin einer der Entwickler.
Iterable
! =Iterator
Ich möchte nur auf eine scheinbar offensichtliche Lösung hinweisen, die NICHT funktioniert:
List list = Stream.generate (iterator :: next) .collect (Collectors.toList ());
Das liegt daran, Stream#generate(Supplier<T>)
dass nur unendliche Streams erstellt werden können und nicht erwartet wird, NoSuchElementException
dass das Argument ausgelöst wird (das Iterator#next()
wird am Ende der Fall sein ).
Die Antwort des xehpuk sollte stattdessen verwendet werden, wenn Sie den Iterator → Stream → List-Weg wählen .
benutze Google Guave !
Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);
++
Hier in diesem Fall for loop
ist es besser, wenn Sie den schnellstmöglichen Weg wollen .
Der Iterator über eine Stichprobengröße von 10,000 runs
Takes, 40 ms
wie für Schleifen-Takes2 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));
Dies setzt voraus, dass die Liste Zeichenfolgen enthält.
for
Schleife und der Zugriff auf die Elemente einer Liste mit get(i)
schneller als die Verwendung eines Iterators ... aber das hat das OP nicht verlangt, er erwähnte ausdrücklich, dass ein Iterator als Eingabe angegeben wird.
get(int)
Schleife sehen Sie nur 100.000 der 1-Meter-Einträge. Wenn Sie diese Schleife in ändern, werden it.size()
Sie feststellen, dass diese beiden Methoden nahe an der gleichen Geschwindigkeit liegen. Im Allgemeinen liefern diese Arten von Java-Geschwindigkeitstests nur begrenzte Informationen zur tatsächlichen Leistung und sollten skeptisch betrachtet werden.