Sind Java-Streams Stufen sequenziell?

7

Ich habe eine Frage zum sequentiellen Status der Zwischenstufen - sind die Operationen von einer Stufe auf alle angewendet der Eingabestrom (Elemente) oder sind alle Stufen / Operationen auf jedes Stream-Element angewendet?

Ich bin mir bewusst, dass die Frage vielleicht nicht leicht zu verstehen ist, also werde ich ein Beispiel geben. Bei der folgenden Stream-Verarbeitung:

%Vor%

Meine Erwartung für diesen Code ist, dass er Folgendes ausgeben wird:

%Vor%

Stattdessen lautet die Ausgabe:

%Vor%

Werden die Elemente aufgrund der Konsolenausgabe für alle Stufen nur angezeigt? Oder werden sie auch für alle Stufen nacheinander bearbeitet?

Ich kann die Frage weiter präzisieren, wenn sie nicht klar genug ist.

    
Bogdan Solga 01.07.2017, 15:20
quelle

4 Antworten

14

Dieses Verhalten ermöglicht Optimierung des Codes. Wenn jede Zwischenoperation alle Elemente eines Datenstroms verarbeiten würde, bevor mit der nächsten Zwischenoperation fortgefahren wird, gibt es keine Möglichkeit der Optimierung .

Um also Ihre Frage zu beantworten, bewegt sich jedes Element vertikal nacheinander () (abgesehen von einigen stateful -Operationen, die später besprochen werden) und ermöglicht daher eine Optimierung, wo immer es möglich ist .

Erklärung

In dem Beispiel, das Sie angegeben haben, bewegt sich jedes Element vertikal entlang der Stream-Pipeline, da keine -Operation enthalten ist.

Ein anderes Beispiel: Sie haben nach dem ersten String gesucht, dessen Länge größer ist als 4 . Die Verarbeitung aller Elemente vor der Bereitstellung des Ergebnisses ist unnötig und zeitraubend.

Betrachten Sie diese einfache Illustration:

%Vor%

Die obige Operation filter intermediate wird nicht alle Elemente finden, deren Länge größer als 4 ist und einen neuen Stream von ihnen zurückgeben, sondern was passiert, sobald wir den ersten finden Element, dessen Länge größer ist als 4 , dieses Element geht durch zum .mapToInt welches dann findFirst sagt "Ich habe das erste Element gefunden" und die Ausführung stoppt dort. Daher wird das Ergebnis 12345 sein.

Verhalten zustandsbehafteter und zustandsloser Zwischenoperationen

Beachten Sie, dass, wenn eine stateful intermediate Operation von sorted in einer Stream-Pipeline enthalten ist, diese spezifische Operation den gesamten Stream durchläuft . Wenn Sie darüber nachdenken, macht dies durchaus Sinn, denn um Elemente zu sortieren, müssen Sie alle Elemente sehen, um zu bestimmen, welche Elemente in der Sortierreihenfolge an erster Stelle stehen.

Die Operation distinct intermediate ist ebenfalls eine Stateful-Operation. Wie @Holger jedoch im Gegensatz zu sorted erwähnt hat, muss nicht der gesamte Stream durchlaufen werden, da jedes einzelne Element sofort in der Pipeline übergeben werden kann und a Kurzschlussbedingung.

statusfreie Zwischenoperationen wie filter , map usw. müssen nicht den gesamten Datenstrom durchlaufen und können vertikal ein Element zur gleichen Zeit wie oben beschrieben vertikal bearbeiten.

Schließlich, aber nicht zuletzt, ist es auch wichtig zu beachten, dass, wenn die Terminaloperation ein Kurzschlussvorgang ist, die Terminal-Shortcircting-Methoden abgeschlossen werden können, bevor alle Elemente des zugrundeliegenden Stroms durchlaufen werden.

lesen: Java 8-Stream-Lernprogramm

    
Aominè 01.07.2017, 15:27
quelle
4
  

Ihre Antwort lautet loop fusion . Was wir sehen, ist, dass die vier   Zwischenoperationen filter() – peek() – map() – peek() – println using forEach() which is a kinda terminal operation waren logisch   zusammengefügt, um einen einzigen Durchgang zu bilden. Sie werden ausgeführt in   Reihenfolge für jedes einzelne Element . Dieser Beitritt   Zusammen von Operationen in einem einzigen Durchgang ist eine Optimierungstechnik   bekannt als loop fusion .

Mehr zum Lesen: Quelle

    
snr 01.07.2017 16:02
quelle
2

Eine Zwischenoperation wird immer träge ausgeführt. Das heißt  Sie werden nicht bis zum Erreichen einer Terminaloperation ausgeführt.   Einige der beliebtesten Zwischenoperationen, die in einem Stream verwendet werden

%Vor%

. java-8-streams-cheat-sheet

    
jithin joseph 01.07.2017 15:36
quelle
2

Abgesehen von der Optimierung würde die Reihenfolge der Verarbeitung, die Sie beschreiben würden, nicht für Ströme unbestimmter Länge funktionieren, wie z das:

%Vor%

Zugegebenermaßen macht dieses Beispiel in der Praxis wenig Sinn, aber der Punkt ist, dass DoubleStream.generate() nicht durch eine Sammlung fester Größe unterstützt wird, sondern einen potenziell unendlichen Stream erzeugt. Die einzige Möglichkeit, dies zu verarbeiten, ist Element für Element.

    
biziclop 01.07.2017 16:17
quelle

Tags und Links