Próbuję zmienić niektóre pętle for-each na forEach()
metody lambda, aby odkryć możliwości wyrażeń lambda. Wydaje się, że możliwe jest:
ArrayList<Player> playersOfTeam = new ArrayList<Player>();
for (Player player : players) {
if (player.getTeam().equals(teamName)) {
playersOfTeam.add(player);
}
}
Z lambdą forEach()
players.forEach(player->{if (player.getTeam().equals(teamName)) {playersOfTeam.add(player);}});
Ale następny nie działa:
for (Player player : players) {
if (player.getName().contains(name)) {
return player;
}
}
z lambdą
players.forEach(player->{if (player.getName().contains(name)) {return player;}});
Czy coś jest nie tak w składni ostatniej linii, czy też nie można wrócić z forEach()
metody?
return
w instrukcji lambda wraca z samej lambdy, a nie z tego, co nazywa się lambdą. Kończy strumień na początku („zwarcie”),findFirst
jak pokazano w odpowiedzi Iana Robertsa .Odpowiedzi:
return
Nie powraca z wyrażenia lambda zamiast ze sposobu zawierającego. ZamiastforEach
ciebie potrzebujeszfilter
strumienia:players.stream().filter(player -> player.getName().contains(name)) .findFirst().orElse(null);
Tutaj
filter
ogranicza strumień do tych elementów, które pasują do predykatu, afindFirst
następnie zwracaOptional
z pierwszym pasującym wpisem.Wygląda to na mniej wydajne niż podejście for-loop, ale w rzeczywistości
findFirst()
może powodować zwarcie - nie generuje całego przefiltrowanego strumienia, a następnie wyodrębnia z niego jeden element, a raczej filtruje tylko tyle elementów, ile potrzebuje, aby znajdź pierwszy pasujący. Możesz także użyćfindAny()
zamiast,findFirst()
jeśli niekoniecznie zależy ci na uzyskaniu pierwszego pasującego gracza z (uporządkowanego) strumienia, ale po prostu dowolnego pasującego elementu. Pozwala to na lepszą wydajność, gdy występuje równoległość.źródło
orElse(null)
naOptional
. Głównym celemOptional
jest zapewnienie sposobu wskazania obecności lub braku wartości zamiast przeciążania wartości null (co prowadzi do NPE). Jeślioptional.orElse(null)
go użyjesz , odkupisz wszystkie problemy z wartościami null. Użyłbym go tylko wtedy, gdy nie możesz zmodyfikować dzwoniącego i naprawdę oczekuje wartości null.Optional<Player>
byłaby bardziej naturalnym sposobem dopasowania do paradygmatu strumieni. Chciałem tylko pokazać, jak powielić istniejące zachowanie za pomocą lambd.Proponuję najpierw spróbować zrozumieć Java 8 w całości, w twoim przypadku najważniejsze będą strumienie, lambdy i odwołania do metod.
Nigdy nie należy konwertować istniejącego kodu do kodu Java 8 na podstawie linii, należy wyodrębniać funkcje i konwertować je.
To, co zidentyfikowałem w twoim pierwszym przypadku, jest następujące:
Zobaczmy, jak to robimy, możemy to zrobić w następujący sposób:
To, co tutaj robisz, to:
Collection<Player>
, teraz masz plikStream<Player>
.Predicate<Player>
, mapując każdego gracza na wartość logiczną true, jeśli chcesz ją zachować.Collector
, tutaj możemy użyć jednego ze standardowych kolektorów biblioteki, którym jestCollectors.toList()
.Obejmuje to również dwa inne punkty:
List<E>
overArrayList<E>
.new ArrayList<>()
, w końcu używasz Java 8.Przejdźmy teraz do drugiego punktu:
Znowu chcesz przekonwertować coś ze starszej Javy na Javę 8 bez patrzenia na większy obraz. Na tę część odpowiedział już @IanRoberts , chociaż myślę, że musisz zrobić
players.stream().filter(...)...
to, co zasugerował.źródło
Jeśli chcesz zwrócić wartość logiczną, możesz użyć czegoś takiego (znacznie szybciej niż filtr):
źródło
To mi pomogło:
List<RepositoryFile> fileList = response.getRepositoryFileList(); RepositoryFile file1 = fileList.stream().filter(f -> f.getName().contains("my-file.txt")).findFirst().orElse(null);
Zaczerpnięte z Java 8 Finding Specific Element in List with Lambda
źródło
Możesz również zgłosić wyjątek:
Uwaga:
Ze względu na czytelność każdy krok strumienia powinien być wymieniony w nowej linii.
players.stream() .filter(player -> player.getName().contains(name)) .findFirst() .orElseThrow(MyCustomRuntimeException::new);
jeśli Twoja logika jest luźno „sterowana wyjątkami”, na przykład w kodzie jest jedno miejsce, które wyłapuje wszystkie wyjątki i decyduje, co dalej. Używaj programowania opartego na wyjątkach tylko wtedy, gdy możesz uniknąć zaśmiecania bazy kodu wielokrotnościami,
try-catch
a zgłaszanie tych wyjątków dotyczy bardzo specjalnych przypadków, których się spodziewasz i można je poprawnie obsłużyć).źródło