Ta strona wykorzystuje pliki cookie w celu prezentacji dopasowanych dla Ciebie treści. Możesz włączyć/wyłączyć obsługę plików cookies w swojej przeglądarce.

Dowiedz się więcej

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:

image

Wywołanie:

image

Przeanalizujmy powyższy zapis:

  1. Tworzymy nową listę Stringów (każde miasto to String).
  2. Z listy lotów pobieramy po kolei każdy element.
  3. Sprawdzamy, czy lista miast nie zawiera nazwy lotniska startowego, jeśli nie – dodajemy je do listy. To samo robimy z nazwą lotniska docelowego.
  4. 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:

image

Zmodyfikujmy kod ostatniej metody:

image

Zauważ, że składnia:

image

Została uproszczona do:

image

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:

image

Zmodyfikowane tworzenie obiektów typu Flight w konstruktorze FlightDatabase:

image

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

image

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:

image

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:

image

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:

image

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.

image

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

image

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:

image

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.

image

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!