Ich möchte so etwas erreichen:
items.stream()
.filter(s-> s.contains("B"))
.forEach(s-> s.setState("ok"))
.collect(Collectors.toList());
filtern, dann eine Eigenschaft aus dem gefilterten Ergebnis ändern und das Ergebnis in einer Liste sammeln. Der Debugger sagt jedoch:
collect(Collectors.toList())
kann nicht für den primitiven Typvoid
aufgerufen werden.
Brauche ich dafür 2 Streams?
Die forEach
ist als Terminalbetrieb konzipiert und ja, Sie können nach dem Aufruf nichts mehr tun.
Der idiomatische Weg wäre, zuerst eine Transformation und dann collect()
alles auf die gewünschte Datenstruktur anzuwenden.
Die Transformation kann mit map
durchgeführt werden, das für nicht mutierende Operationen ausgelegt ist.
Wenn Sie eine nicht mutierende Operation ausführen:
items.stream()
.filter(s -> s.contains("B"))
.map(s -> s.withState("ok"))
.collect(Collectors.toList());
dabei ist withState
eine Methode, die eine Kopie des ursprünglichen Objekts einschließlich der bereitgestellten Änderung zurückgibt.
Wenn Sie eine Nebenwirkung haben:
items.stream()
.filter(s -> s.contains("B"))
.collect(Collectors.toList());
items.forEach(s -> s.setState("ok"))
Ersetzen Sie forEach
durch map
.
items.stream()
.filter(s-> s.contains("B"))
.map(s-> {s.setState("ok");return s;})
.collect(Collectors.toList());
forEach
und collect
sind beide Terminaloperationen - Streams müssen nur einen haben. Alles, was einen Stream<T>
zurückgibt, ist ein intermediate operation
, alles andere ist ein terminal operation
.
Widerstehen Sie dem Drang, Nebenwirkungen ohne großen Grund aus dem Inneren des Streams zu ziehen. Erstellen Sie die neue Liste und übernehmen Sie die Änderungen:
List<MyObj> toProcess = items.stream()
.filter(s -> s.contains("B"))
.collect(toList());
toProcess.forEach(s -> s.setState("ok"));
forEach
ist eine Terminaloperation, dh es wird kein Stream-Ergebnis erzeugt. forEach
erzeugt nichts und collect
gibt eine Collection zurück. Was Sie brauchen, ist eine Stream-Operation, die Elemente für Ihre Anforderungen ändert. Diese Operation ist map
, mit der Sie eine Funktion angeben können, die auf jedes Element des Eingabestroms angewendet wird, und einen transformierten Strom von Elementen erzeugt. Also brauchst du so etwas wie:
items.stream()
.filter (s -> s.contains("B"))
.map (s -> { s.setState("ok"); return s; }) // need to return a value here
.collect(Collectors.toList());
Eine Alternative ist die Verwendung von peek
, deren Zweck es ist, auf jedes durchlaufende Element eine Funktion anzuwenden.
items.stream()
.filter (s -> s.contains("B"))
.peek (s -> s.setState("ok")) // no need to return a value here
.collect(Collectors.toList());
Sie können nicht zwei Terminaloperationen auf demselben Stream ausführen.
Sie können den Status des Objekts in einer Zwischenoperation festlegen, z. B. map
:
List<YourClass> list =
items.stream()
.filter(s-> s.contains("B"))
.map(s-> {
s.setState("ok");
return s;
})
.collect(Collectors.toList());
items.stream()
.filter(s-> s.contains("B"))
.peek(s-> s.setState("ok"))
.collect(Collectors.toList());
Stream peek (Consumer-Aktion) Gibt einen Stream aus .__ zurück. der Elemente dieses Streams, zusätzlich das bereitgestellte Aktion für jedes Element, wenn Elemente aus dem resultierenden .__ verbraucht werden. Strom. Dies ist eine Zwischenoperation.
Bei parallelen Stream-Pipelines kann die Aktion an beliebiger Stelle aufgerufen werden Zeit und in welchem Thread das Element von der .__ zur Verfügung gestellt wird. Upstream-Betrieb. Wenn die Aktion den gemeinsam genutzten Status ändert, lautet sie verantwortlich für die Bereitstellung der erforderlichen Synchronisation.
API-Hinweis: Diese Methode unterstützt hauptsächlich das Debuggen, wobei Sie möchten die Elemente sehen, wenn sie an einem bestimmten Punkt in einer .__ vorbei fließen. Pipeline:
Stream.of("one", "two", "three", "four") .filter(e -> e.length() > 3) .peek(e -> System.out.println("Filtered value: " + e)) .map(String::toUpperCase) .peek(e -> System.out.println("Mapped value: " + e)) .collect(Collectors.toList()); Parameters: action - a non-interfering action to perform on the elements as they are consumed
aus dem Stream kehrt zurück: Der neue Stream