2016-03-28 15 views
24

Sto imparando le nuove funzionalità di Java 8 e mentre sperimentavo gli stream (java.util.stream.Stream) e i collezionisti, mi sono reso conto che un flusso non può essere usato due volte. C'è un modo per riutilizzarlo?Esiste un modo per riutilizzare un flusso in java 8?

+0

Sì, i flussi possono essere riutilizzati, solo se nessuno degli usi non chiama alcuna operazione terminale su di esso. –

+0

Possibile duplicato di [Copia un flusso per evitare "il flusso è già stato utilizzato o chiuso" (java 8)] (http://stackoverflow.com/questions/23860533/copy-a-stream-to-avoid-stream- has-already-been-operated-upon-or-closed-java-8) – Andrejs

risposta

32

Dal documentation:

Un flusso deve essere azionato su (invocare un'operazione flusso intermedia o terminale) solo una volta.

Un'implementazione del flusso può lanciare IllegalStateException se rileva che il flusso viene riutilizzato.

Quindi la risposta è no, i flussi non sono pensati per essere riutilizzati.

1

L'idea del flusso è che è una volta. Ciò consente di creare origini non rientranti (ad esempio, leggendo le linee dalla connessione di rete) senza memoria intermedia. Se, invece, desidera riutilizzare il contenuto Stream, è possibile scaricare nella collezione intermedia per ottenere il "copia cartacea":

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 

Se non si desidera materializzarsi il torrente, in alcuni casi ci sono modi per fare diverse cose con lo stesso flusso in una volta. Ad esempio, è possibile fare riferimento alla domanda this o this per i dettagli.

23

Se si desidera avere l'effetto di riutilizzare un flusso, è possibile avvolgere l'espressione di flusso in un fornitore e chiamare myStreamSupplier.get() ogni volta che si desidera uno nuovo. Ad esempio,

Supplier<Stream<String>> sup =() -> 
     someList.stream(); 
List<String> nonEmptyStrings = sup.get().filter(s -> !s.isEmpty()).collect(Collectors.toList()); 
Set<String> uniqueStrings = sup.get().collect(Collectors.toSet()); 
+1

Questo non riutilizza lo stream. Il fornitore crea semplicemente un nuovo stream da utilizzare ogni volta che viene richiamato. – axiopisty

+5

Ecco perché Hank D ha detto "l'effetto di". È ancora più pulito e codice più riutilizzabile. – Andrejs

9

Come altri hanno detto, "no non si può".

Ma è utile ricordare la portata di mano summaryStatistics() per molte operazioni di base:

Così, invece di:

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(); 

È possibile:

// Can also be DoubleSummaryStatistics from mapToDouble() 

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

stats.getAverage(); 
stats.getMin(); 
stats.getMax(); 
Problemi correlati