Dokończenie aplikacji
Hej!
Zaczynamy ostatnią część naszego Wyzwania. Na dobry początek omówmy sobie pracę domową z poprzedniej części. Twój kod powinien być podobny do poniższego:

Wywołanie:

Przeanalizujmy powyższy zapis:
- Tworzymy nową listę Stringów (każde miasto to String).
- Z listy lotów pobieramy po kolei każdy element.
- Sprawdzamy, czy lista miast nie zawiera nazwy lotniska startowego, jeśli nie – dodajemy je do listy. To samo robimy z nazwą lotniska docelowego.
- Na koniec zwracamy uzupełnioną listę.
Prawda, że proste?
To jednak nie wszystko. Nasz kod można jeszcze lepszy! Za każdym razem, gdy przechodzimy po kolekcji, używamy pętli for
, a następnie pobieramy obiekt z danym indeksem. Technicznie jest to poprawny sposób, jednak można to zrobić lepiej, za pomocą pętli for each
. Jej składnia wygląda następująco:

Zmodyfikujmy kod ostatniej metody:

Zauważ, że składnia:

Została uproszczona do:

Podobny zabieg zastosuj do pozostałych pętli.
Dodajemy cenę lotu
Klasa Flight
jest prostą strukturą – zawiera tylko dwie zmienne typu String. Dodajmy kolejną zmienną, którą będzie cena lotu. Samo dodanie typu w klasie nie wystarczy. Należy również zmodyfikować metodę getDetails()
, aby poprawnie wyświetlać wartości. Po modyfikacji konstruktora, konieczne będzie przekazanie nowego parametru w trakcie tworzenia poszczególnych obiektów.
Zmodyfikowana klasa Flight
:

Zmodyfikowane tworzenie obiektów typu Flight
w konstruktorze FlightDatabase
:

Mamy nową zmienną, czas ją więc wykorzystać. Zacznijmy od metody, która zwróci najtańszy lot.

W metodzie utworzyliśmy zmienną cheapestFlight
, ale nie przypisaliśmy do niej żadnej wartości (null). Następnie w pętli for each
iterujemy po wszystkich lotach z bazy. Jeśli najtańszy lot nie istnieje lub cena obecnie przetwarzanego lotu jest niższa od ceny najtańszego lotu, podmieniamy wartości. W ten sposób uzyskujemy informację o najtańszym locie.
Wyświetlenie:

Teraz krótkie zadanie dla Ciebie. Utwórz nową metodę, która zwróci najtańszy lot z podanego miasta.
Swoje rozwiązanie możesz porównać z poniższym kodem:

Nie musimy na nowo tworzyć metody wyszukującej loty z podanego miasta – mamy odpowiednią metodę, tylko ją wywołujemy. Na podstawie zwróconej listy, szukamy najtańszego lotu.
Wyszukiwanie lotu z przesiadką
Płynnie przechodzimy do naszego celu: wyszukiwanie lotu z przesiadką. Zastanówmy się najpierw teoretycznie, jak to powinno wyglądać. Podajemy dwa miasta: startowe i końcowe. Zaczynamy od wyszukania wszystkich lotów z miasta startowego, w efekcie czego otrzymujemy listę. Następnie szukamy lotów, które kończą się w mieście końcowym, a efektem również jest lista. Mamy dwie listy, które trzeba połączyć. Jak? Jeśli lotnisko docelowe z pierwszej listy równe jest lotnisku startowemu z drugiej listy, otrzymaliśmy podróż z przesiadką (dwa loty). Spróbuj samodzielnie dodać implementację metody getFlights(String start, String end)
.
Rozwiązanie:

Zgodnie z tym, co powiedziane zostało wcześniej, najpierw wyszukujemy loty z miasta startowego, następnie szukamy lotów, które kończą się w mieście docelowym. Tworzymy pustą listę, która będzie przechowywać wyniki. Iterujemy po jednej i drugiej kolekcji, a jeśli miasta się zgadzają, dodajemy oba loty do listy.
Otrzymany wynik:
Flight from Paris to Madrid costs 180
Flight from Madrid to Porto costs 102
Wygląda prawidłowo, jednak jak zawsze, można to zrobić lepiej. Utwórzmy teraz klasę Journey
, która będzie przechowywać dwa loty.

Czas użyć nowej klasy! Spróbuj samodzielnie zmodyfikować metodę getFlights
.

Zmieniony został typ zwracany, wcześniej była to lista obiektów typu Flight
, teraz to lista obiektów Journey
. W pętli nie dodajemy dwóch obiektów do listy wynikowej. Zamiast tego tworzymy nowy obiekt typu Journey
, który zawiera dwa obiekty Flight
.
Po wywołaniu:

Otrzymamy mało czytelny wynik:
[Journey@10f87f48]
Moglibyśmy utworzyć dodatkową metodę displayJourneyDetails()
, ale jej implementacja będzie bardzo podobna do metody displayFlightDetails()
. Jest inny sposób.
Jeśli wywołamy System.out.println(nazwaZmiennej)
, a zmienna jest typu obiektowego, automatycznie zostanie wywołana metoda toString()
, zwracająca Stringa z tego obiektu. Rozwiązanie? Dodajmy metodę toString()
do klasy Journey
.

Po uruchomieniu, wyświetlony wynik zmieni się na [Flight from Paris to Porto with stop at Madrid costs 282]
. To dokładnie to, czego oczekiwaliśmy!
Dalszy rozwój aplikacji

Gratulacje! W ciągu tego Wyzwania udało Ci się napisać funkcjonalną wyszukiwarkę lotów. Mamy nadzieję, że przygoda z Javą Ci się podobała!
To oczywiście nie koniec drogi. Możesz dalej samodzielnie rozwijać aplikację według własnych pomysłów, lub korzystając ze wskazówek poniżej:
- jeśli jest kilka lotów z przesiadką, zwróć tylko najtańszy,
- dodaj długość lotu do klasy
Flight
i użyj nowo utworzonej zmiennej, - podaj do metody dwa miasta. Jeśli jest lot bezpośredni, zwróć go, jeśli nie, wyszukaj lot z przesiadką.
Jak widzisz, jedynym ograniczeniem jest Twoja wyobraźnia. Zakodowanie powyższych funkcjonalności nie powinno sprawdzić dużych problemów. Tak zazwyczaj wygląda programowanie. Najtrudniej jest usiąść do komputera, a każdy kolejny etap jest łatwiejszy :)
Dzięki za udział w Wyzwaniu i do zobaczenia na bootcampie!