622 Stimmen

Wie konvertiert man einen Iterator in einen Stream?

Ich suche nach einer prägnanten Möglichkeit, einen Iterator in einen Stream umzuwandeln oder genauer gesagt, den Iterator als Stream zu "anzeigen".

Aus Leistungsgründen möchte ich eine Kopie des Iterators in einer neuen Liste vermeiden:

Iterator sourceIterator = Arrays.asList("A", "B", "C").iterator();
Collection copyList = new ArrayList();
sourceIterator.forEachRemaining(copyList::add);
Stream targetStream = copyList.stream();

Basierend auf einigen Vorschlägen in den Kommentaren habe ich auch versucht, Stream.generate zu verwenden:

public static void main(String[] args) throws Exception {
    Iterator sourceIterator = Arrays.asList("A", "B", "C").iterator();
    Stream targetStream = Stream.generate(sourceIterator::next);
    targetStream.forEach(System.out::println);
}

Ich erhalte jedoch eine NoSuchElementException (da keine Aufruf von hasNext stattfindet)

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 mir StreamSupport und Collections angesehen, aber nichts gefunden.

701voto

assylias Punkte 308529

Ein Weg ist, einen Spliterator aus dem Iterator zu erstellen und diesen als Grundlage für Ihren Stream zu verwenden:

Iterator sourceIterator = Arrays.asList("A", "B", "C").iterator();
Stream targetStream = StreamSupport.stream(
          Spliterators.spliteratorUnknownSize(sourceIterator, Spliterator.ORDERED),
          false);

Alternativ, was vielleicht lesbarer ist, ist die Verwendung eines Iterable - und die Erstellung eines Iterable aus einem Iterator ist sehr einfach mit Lambdas, da Iterable ein Funktionsinterface ist:

Iterator sourceIterator = Arrays.asList("A", "B", "C").iterator();

Iterable iterable = () -> sourceIterator;
Stream targetStream = StreamSupport.stream(iterable.spliterator(), false);

172voto

numéro6 Punkte 3592

Seit Version 21 bietet die Guava-Bibliothek Streams.stream(iterator)

Es tut, was die Antwort von @assylias zeigt Antwort zeigt.

109voto

Matan Punkte 1377

Toller Vorschlag! Hier ist meine wiederverwendbare Umsetzung:

public class StreamUtils {

    public static  Stream asStream(Iterator sourceIterator) {
        return asStream(sourceIterator, false);
    }

    public static  Stream asStream(Iterator sourceIterator, boolean parallel) {
        Iterable iterable = () -> sourceIterator;
        return StreamSupport.stream(iterable.spliterator(), parallel);
    }
}

Und Verwendung (stellen Sie sicher, dass Sie asStream statisch importieren):

List aPrefixedStrings = asStream(sourceIterator)
                .filter(t -> t.startsWith("A"))
                .collect(toList());

94voto

PhilipRoman Punkte 1205

Dies ist in Java 9 möglich.

Stream.generate(() -> null)
    .takeWhile(x -> iterator.hasNext())
    .map(n -> iterator.next())
    .forEach(System.out::println);

12voto

sneha Punkte 117
import com.google.common.collect.Streams;

und benutze Streams.stream(iterator) :

Streams.stream(iterator)
       .map(v-> function(v))
       .collect(Collectors.toList());

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X