Poznaję nowe funkcje Java 8 i podczas eksperymentowania ze strumieniami (java.util.stream.Stream) i kolekcjonerami, zdałem sobie sprawę, że strumienia nie można użyć dwa razy. Czy istnieje sposób na jego ponowne wykorzystanie?Czy istnieje sposób na ponowne wykorzystanie Stream w java 8?
Odpowiedz
Strumień powinien pracować na (pośrednie lub wywoływania działania terminala Stream) tylko raz.
Implementacja strumienia może rzucić IllegalStateException, jeśli wykryje, że strumień jest ponownie wykorzystywany.
Odpowiedź brzmi: nie, strumienie nie są przeznaczone do ponownego wykorzystania.
Cała idea Streamu polega na tym, że jest jednorazowy. Pozwala to na tworzenie nieodnotowalnych źródeł (na przykład czytanie linii z połączenia sieciowego) bez pośredniego przechowywania. Jeśli jednak chcesz użyć ponownie zawartość Stream, można zrzucić go do kolekcji pośredniego uzyskać „wydruk”:
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
Jeśli nie chcesz, aby urzeczywistnić ten strumień, w niektórych przypadkach istnieje są sposoby na zrobienie kilku rzeczy jednocześnie z tym samym strumieniem. Na przykład możesz zapoznać się z this lub this, aby uzyskać szczegółowe informacje.
Jeśli chcesz uzyskać efekt ponownego wykorzystania strumienia, możesz zawinąć wyrażenie strumienia w dostawcy i wywołać myStreamSupplier.get(), gdy tylko chcesz nowy. Na przykład:
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());
Tak jak inni mówili: "nie, nie możesz".
Ale warto pamiętać poręczny summaryStatistics()
dla wielu podstawowych operacji:
więc zamiast:
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();
Można:
// Can also be DoubleSummaryStatistics from mapToDouble()
IntSummaryStatistics stats = personList.stream()
.mapToInt(p-> p.getAge())
.summaryStatistics();
stats.getAverage();
stats.getMin();
stats.getMax();
Tak, strumienie mogą być ponownie wykorzystane, jedynie jeśli żadne z zastosowań nie wywołuje na nim żadnych operacji terminalowych. –
Możliwy duplikat [Kopiuj strumień, aby uniknąć "strumień był już obsługiwany lub zamknięty" (java 8)] (http://stackoverflow.com/questions/23860533/copy-a-stream-to-avoid-stream- został już użyty-na-lub-zamknął-java-8) – Andrejs