2016-03-28 10 views
24

Ich lerne die neuen Funktionen von Java 8, und während ich mit Streams (java.util.stream.Stream) und Collectors experimentiere, habe ich festgestellt, dass ein Stream nicht zweimal verwendet werden kann. Gibt es einen Weg, ihn wiederzuverwenden?Gibt es eine Möglichkeit, einen Stream in Java 8 wiederzuverwenden?

+0

Ja, Ströme wiederverwendet werden, nur dann, wenn Jede der Anwendungen ruft keine Terminaloperationen darauf auf. –

+0

Mögliches Duplikat von [Kopieren Sie einen Stream, um zu vermeiden, dass der Stream bereits bearbeitet oder geschlossen wurde (Java 8)] (http://stackoverflow.com/questions/23860533/copy-a-stream-to-avid-stream- has-bereits-operated-on-or-closed-java-8) – Andrejs

Antwort

32

Vom documentation:

Ein Strom nur einmal betätigt werden sollte (Aufrufen eines Zwischen- oder Terminalstrom-Betrieb).

Eine Stream-Implementierung kann IllegalStateException auslösen, wenn sie erkennt, dass der Stream wiederverwendet wird.

Also die Antwort ist nein, Streams sollen nicht wiederverwendet werden.

1

Die ganze Idee des Streams ist, dass es einmalig ist. Dadurch können Sie nicht-reentrierbare Quellen (z. B. das Lesen der Zeilen von der Netzwerkverbindung) ohne Zwischenspeicherung erstellen. Wenn Sie jedoch das Streamen von Inhalten wiederverwenden möchten, können Sie es in die Zwischen Sammlung werfen den „hard copy“ zu bekommen:

Stream<MyType> stream = // get the stream from somewhere 
List<MyType> list = stream.collect(Collectors.toList()); // materialize the stream contents 
list.stream().doSomething // create a new stream from the list 
list.stream().doSomethingElse // create one more stream from the list 

Wenn Sie nicht wollen, um den Strom materialisieren, da in einigen Fällen sind Möglichkeiten, mehrere Dinge gleichzeitig mit demselben Stream zu tun. Zum Beispiel können Sie sich auf this oder this Frage für Details beziehen.

23

Wenn Sie den Effekt der Wiederverwendung eines Streams nutzen möchten, können Sie den Stream-Ausdruck in einen Lieferanten verpacken und myStreamSupplier.get() aufrufen, wenn Sie einen neuen Stream wünschen. Zum Beispiel

+1

Dies wird den Stream nicht wiederverwenden. Der Lieferant erstellt nur einen neuen Stream, der bei jedem Aufruf verwendet wird. – axiopisty

+5

Deshalb sagte Hank D "die Wirkung von". Es ist immer noch sauberer und wiederverwendbarer Code. – Andrejs

9

Wie andere gesagt haben, "nein, du kannst nicht".

Aber es ist nützlich, um die handliche summaryStatistics() für viele grundlegende Vorgänge zu erinnern:

Also statt:

List<Person> personList = getPersons(); 

personList.stream().mapToInt(p -> p.getAge()).average().getAsDouble(); 
personList.stream().mapToInt(p -> p.getAge()).min().getAsInt(); 
personList.stream().mapToInt(p -> p.getAge()).max().getAsInt(); 

Sie können:

// Can also be DoubleSummaryStatistics from mapToDouble() 

IntSummaryStatistics stats = personList.stream() 
             .mapToInt(p-> p.getAge()) 
             .summaryStatistics(); 

stats.getAverage(); 
stats.getMin(); 
stats.getMax(); 
Verwandte Themen