Mam problem ze strumieniem Java 8 foreach próbującym przejść do następnego elementu w pętli. Nie mogę ustawić polecenia jak continue;
, return;
działa tylko, ale w tym przypadku wyjdziesz z pętli. Muszę przejść do następnego elementu w pętli. Jak mogę to zrobić?
Przykład (nie działa):
try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
filteredLines = lines.filter(...).foreach(line -> {
...
if(...)
continue; // this command doesn't working here
});
}
Przykład (działający):
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!
}
continue
przejście do następnego elementu bez żadnych zmian funkcjonalnych.else
bloku. Jeśli nie ma nic późniejcontinue
, porzuć blok if i kontynuuj: są bezużyteczne.Odpowiedzi:
Używanie
return;
będzie działać dobrze. Nie przeszkodzi to w ukończeniu pełnej pętli. Przestanie tylko wykonywać bieżącą iteracjęforEach
pętli.Wypróbuj następujący mały program:
Wynik:
Zwróć uwagę, jak
return;
jest wykonywany dlab
iteracji, alec
drukuje w następnej iteracji dobrze.Dlaczego to działa?
Powodem, dla którego zachowanie wydaje się początkowo nieintuicyjne, jest to, że jesteśmy przyzwyczajeni do
return
instrukcji przerywającej wykonanie całej metody. W tym przypadku spodziewamy się, żemain
wykonanie metody jako całości zostanie zatrzymane.Należy jednak zrozumieć, że wyrażenie lambda, takie jak:
... naprawdę należy traktować jako swoją własną, odrębną „metodę”, całkowicie odrębną od
main
metody, mimo że jest dogodnie umiejscowiona w jej obrębie. Tak naprawdęreturn
instrukcja zatrzymuje tylko wykonanie wyrażenia lambda.Drugą rzeczą, którą należy zrozumieć, jest to, że:
... jest po prostu zwykłą pętlą pod okładkami, która wykonuje wyrażenie lambda dla każdej iteracji.
Mając na uwadze te 2 punkty, powyższy kod można przepisać w następujący równoważny sposób (tylko w celach edukacyjnych):
Dzięki temu „mniej magicznemu” odpowiednikowi kodu zakres
return
instrukcji staje się bardziej widoczny.źródło
Inne rozwiązanie: przejdź przez filtr z odwróconymi warunkami: Przykład:
można zastąpić
Wydaje się, że najprostszym podejściem jest użycie „powrotu”; chociaż.
źródło
Lambda, do której przechodzisz,
forEach()
jest oceniana dla każdego elementu otrzymanego ze strumienia. Sama iteracja nie jest widoczna z zakresu lambda, więc nie możnacontinue
jej tak, jakbyforEach()
była makrem preprocesora C. Zamiast tego możesz warunkowo pominąć pozostałe zawarte w nim instrukcje.źródło
Możesz użyć prostej
if
instrukcji zamiast kontynuować. Więc zamiast sposobu, w jaki masz swój kod, możesz spróbować:Predykat w instrukcji if będzie po prostu przeciwieństwem predykatu w
if(pred) continue;
instrukcji, więc po prostu użyj!
(nie logiczne).źródło