Ich habe ein Problem mit dem Stream von Java 8 foreach, der versucht, zum nächsten Element in der Schleife zu wechseln. Ich kann den Befehl nicht wie setzen continue;
nur return;
funktioniert, aber Sie verlassen die Schleife in diesem Fall. Ich muss zum nächsten Element in der Schleife übergehen. Wie kann ich das machen?
Beispiel (funktioniert nicht):
try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
filteredLines = lines.filter(...).foreach(line -> {
...
if(...)
continue; // this command doesn't working here
});
}
Beispiel (funktioniert):
try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
filteredLines = lines.filter(...).collect(Collectors.toList());
}
for(String filteredLine : filteredLines){
...
if(...)
continue; // it's working!
}
Verwenden return;
wird gut funktionieren. Es wird nicht verhindern, dass die vollständige Schleife abgeschlossen wird. Es wird nur die Ausführung der aktuellen Iteration von stoppen forEach
Schleife.
Probieren Sie das folgende kleine Programm aus:
public static void main(String[] args) {
ArrayList<String> stringList = new ArrayList<>();
stringList.add("a");
stringList.add("b");
stringList.add("c");
stringList.stream().forEach(str -> {
if (str.equals("b")) return; // only skips this iteration.
System.out.println(str);
});
}
Ausgabe:
a
c
Beachten Sie, wie die return;
wird für die ausgeführt b
Iteration, aber c
druckt auf der folgenden Iteration ganz gut.
Warum funktioniert das?
Der Grund, warum das Verhalten zunächst unintuitiv erscheint, liegt darin, dass wir daran gewöhnt sind return
Anweisung, die die Ausführung der gesamten Methode unterbricht. In diesem Fall erwarten wir also die main
Methodenausführung als Ganzes angehalten werden.
Was jedoch verstanden werden muss, ist, dass ein Lambda-Ausdruck, wie zum Beispiel:
str -> {
if (str.equals("b")) return;
System.out.println(str);
}
… muss wirklich als eigene “Methode” betrachtet werden, völlig getrennt von der main
Methode, obwohl es sich bequem darin befindet. Also wirklich, die return
-Anweisung hält nur die Ausführung des Lambda-Ausdrucks an.
Die zweite Sache, die verstanden werden muss, ist Folgendes:
stringList.stream().forEach()
… ist wirklich nur eine normale Schleife unter der Decke, die den Lambda-Ausdruck für jede Iteration ausführt.
Unter Berücksichtigung dieser 2 Punkte kann der obige Code auf die folgende äquivalente Weise umgeschrieben werden (nur für Bildungszwecke):
public static void main(String[] args) {
ArrayList<String> stringList = new ArrayList<>();
stringList.add("a");
stringList.add("b");
stringList.add("c");
for(String s : stringList) {
lambdaExpressionEquivalent(s);
}
}
private static void lambdaExpressionEquivalent(String str) {
if (str.equals("b")) {
return;
}
System.out.println(str);
}
Mit diesem „weniger magischen“ Code-Äquivalent wird der Umfang der return
Aussage wird deutlicher.
Eine andere Lösung: Gehen Sie durch einen Filter mit Ihren invertierten Bedingungen: Beispiel:
if(subscribtion.isOnce() && subscribtion.isCalled()){
continue;
}
kann ersetzt werden durch
.filter(s -> !(s.isOnce() && s.isCalled()))
Der einfachste Ansatz scheint die Verwendung von “return;” zu sein. obwohl.
Das Lambda, zu dem Sie übergehen forEach()
wird für jedes aus dem Stream empfangene Element ausgewertet. Die Iteration selbst ist innerhalb des Lambda-Bereichs nicht sichtbar, also können Sie das nicht continue
es als ob forEach()
waren ein C-Präprozessor-Makro. Stattdessen können Sie die restlichen Anweisungen darin bedingt überspringen.
Sie können eine einfache verwenden if
Anweisung statt fortzusetzen. Anstelle der Art und Weise, wie Sie Ihren Code haben, können Sie Folgendes versuchen:
try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
filteredLines = lines.filter(...).foreach(line -> {
...
if(!...) {
// Code you want to run
}
// Once the code runs, it will continue anyway
});
}
Das Prädikat in der if-Anweisung ist genau das Gegenteil des Prädikats in Ihrer if(pred) continue;
Anweisung, also einfach verwenden !
(logisch nicht).
Ich muss zum nächsten Element in der Schleife übergehen.
– Viktor M.
18. September 2015 um 14:54 Uhr
Sein Punkt ist, mit dem Code, den Sie gezeigt haben, das nicht zu haben
continue
würde trotzdem ohne funktionale Änderungen zum nächsten Punkt übergehen.– DoppeltDoppelt
18. September 2015 um 14:55 Uhr
Wenn das Ziel darin besteht, die Ausführung von Zeilen zu vermeiden, die nach dem Aufruf zum Fortfahren kommen und die Sie uns nicht zeigen, fügen Sie einfach alle diese Zeilen in ein ein
else
Block. Wenn nichts danach kommtcontinue
dann den if-Block und den Continue löschen: Sie sind nutzlos.– JB Nizet
18. September 2015 um 15:02 Uhr