Ich suche nach einer prägnanten Möglichkeit, einen Iterator
in einen Stream
oder genauer zu konvertieren, um den Iterator als Stream "anzuzeigen".
Aus Leistungsgründen möchte ich eine Kopie des Iterators in einer neuen Liste vermeiden:
Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();
Collection<String> copyList = new ArrayList<String>();
sourceIterator.forEachRemaining(copyList::add);
Stream<String> targetStream = copyList.stream();
Aufgrund einiger Vorschläge in den Kommentaren habe ich auch versucht zu verwenden Stream.generate
:
public static void main(String[] args) throws Exception {
Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();
Stream<String> targetStream = Stream.generate(sourceIterator::next);
targetStream.forEach(System.out::println);
}
Ich bekomme jedoch eine NoSuchElementException
(da es keinen Aufruf von gibt hasNext
)
Exception in thread "main" java.util.NoSuchElementException
at java.util.AbstractList$Itr.next(AbstractList.java:364)
at Main$$Lambda$1/1175962212.get(Unknown Source)
at java.util.stream.StreamSpliterators$InfiniteSupplyingSpliterator$OfRef.tryAdvance(StreamSpliterators.java:1351)
at java.util.Spliterator.forEachRemaining(Spliterator.java:326)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at Main.main(Main.java:20)
Ich habe angeschaut StreamSupport
und Collections
aber nichts gefunden.
Stream.generate(iterator::next)
funktioniert?Antworten:
Eine Möglichkeit besteht darin, einen Spliterator aus dem Iterator zu erstellen und diesen als Grundlage für Ihren Stream zu verwenden:
Eine Alternative, die vielleicht besser lesbar ist, ist die Verwendung eines Iterable - und das Erstellen eines Iterables aus einem Iterator ist mit Lambdas sehr einfach, da Iterable eine funktionale Schnittstelle ist:
quelle
sourceIterator.next()
bevor Sie den Stream verwenden, und Sie werden den Effekt sehen (das erste Element wird vom Stream nicht gesehen).Iterable<String> iterable = () -> sourceIterator;
. Ich muss zugeben, dass ich einige Zeit gebraucht habe, um zu verstehen.Iterable<T>
ist eine,FunctionalInterface
die nur eine abstrakte Methode hatiterator()
. Dies() -> sourceIterator
gilt auch für einen Lambda-Ausdruck, der eineIterable
Instanz als anonyme Implementierung instanziiert .() -> sourceIterator;
ist eine verkürzte Form vonnew Iterable<>() { @Override public Iterator<String> iterator() { return sourceIterator; } }
Seit Version 21 bietet die Guava-Bibliothek
Streams.stream(iterator)
Es tut , was @ assylias ‚s Antwort zeigt .
quelle
Toller Vorschlag! Hier ist meine wiederverwendbare Sichtweise:
Und Verwendung (stellen Sie sicher, dass asStream statisch importiert wird):
quelle
Dies ist in Java 9 möglich.
quelle
.parallel()
Streams zu funktionieren . Sie erscheinen auch etwas langsamer als das ÜbergehenSpliterator
, selbst für die sequentielle Verwendung.parallel
es funky sein mag, ist die Einfachheit erstaunlich.Create
Spliterator
fromIterator
usingSpliterators
class enthält mehr als eine Funktion zum Erstellen eines Spliterators. Hier wird beispielsweise verwendetspliteratorUnknownSize
, um den Iterator als Parameter abzurufen und anschließend Stream mithilfe von zu erstellenStreamSupport
quelle
und verwenden
Streams.stream(iterator)
:quelle
Verwenden
Collections.list(iterator).stream()...
quelle