Przykład
Transkrypt
Przykład
Programowanie w Javie Wykład 8: Kolekcje Wprowadzenie • Programy zazwyczaj operują na dużej liczbie danych • Tablice przechowują dane jednego typu, mają ustalony rozmiar, nie można powiększać/zmniejszać zdefiniowanej tablicy w zależności od tego ile danych potrzebujemy. Stąd potrzeba innych struktur danych, które nie będą miały ograniczeń tablic. • Praktycznie każdy współczesny język programowania obiektowego posiada zestaw kolekcji czyli klas definiujących dynamiczne struktury danych. Obiekty takich klas służą do przechowywania innych obiektów i nie mają takich ograniczeń jak tablice Krótko: kolekcje to klasy definiujące struktury danych o większych możliwościach niż tablice • • • Typy sparametryzowane dobrze nadają się do definiowania kolekcji, bo pozwalają uzyskać odpowiedni poziom ogólności. W bibliotece Javy jest wiele kolekcji i wystarczają, aby obsłużyć większość sytuacji, nie ma konieczności tworzyć własnych, ale konieczne jest rozumienie dokumentacji Kolekcje należą do pakietu java.util. Konieczny import. Przykład kolekcji: ArrayList (cz. 1) ArrayList - samorozszerzalna tablica ArrayList jest klasą generyczną (zobacz dokumentację): public class ArrayList<E> extends AbstractList<E> implements List<E>,RandomAccess, Cloneable, Serializable Utworzenie kolekcji ArrayList: // kolekcja obiektów typu String ArrayList<Integer>() // kolekcja obiektów typu Integer ArrayList<String> s = new ArrayList<String>() ArrayList<Integer> i = new class Osoba{ String imie; int wiek; } ArrayList<Osoba> o = new ArrayList<Osoba>() // kolekcja obiektów typu Osoba Przykład kolekcji: ArrayList (cz. 1) Wybrane metody kolekcji ArrayList: – kolekcja nie ma stałego rozmiaru: • można do niej dodać element metodami: add(Object), add(int,Object) gdzie Object - to element jaki chcemy dodać, zaś int - to na którym miejscu (pod jakim indeksem) ma być dodany • można z niej usunąć element metodami: remove(Object),remove(int) gdzie Object to element jaki usunąć, zaś int to indeks elementu, który ma być usunięty – do sprawdzenia czy dany element jest w kolekcji można użyć metody contains(Object), zamiast robić to za pomocą pętli przebiegając całą kolekcję – Inne metody: • isEmpty() - zwraca true jeśli kolekcja jest pusta • indexOf(Object) - zwraca indeks pierwszego wystąpienia elementu Object w tablicy ArrayList (elementy są numerowane od zera tak jak w zwykłych tablicach) lub -1 jeśli nie ma elementu • size() - zwraca liczbę elementów aktualnie znajdujących się w kolekcji Przykład: Przyklady.java odkomentuj "Kolekcja ArrayList" Sortowanie kolekcji: metoda sort W klasie java.util.Collections jest metoda statyczna sort, która porządkuje kolekcje: public static <T extends Comparable<? super T>> void sort(List<T> list) Wczytajmy miasta z pliku do kolekcji ArrayList i uporządkujmy je alfabetycznie. ArrayList implementuje interfejs List (zobacz slajd 3) więc dzięki polimorfizmowi obiekt klasy ArrayList może być argumentem metody sort Jaki obiekt może być parametrem (zobacz slajd 8 i następne): <T extends Comparable<? super T>> Elementami ArrayList są obiekty typu String. Sortowanie będzie alfabetyczne. Przykład: Przyklady.java odkomentuj "Przykład Sortowanie napisów" Elementami ArrayList są obiekty typu liczbowego: Float, Integer itd. (potomne klasy Number). Sortowanie będzie wg numerów. Przykład: Przyklady.java odkomentuj "Przykład Sortowanie liczb" Od czego zależy jakie jest kryterium sortowania? O tym na kolejnych slajdach (zobacz slajd 8 i następne). Inne kolekcje Stack - Stos Przykład: Przyklady.java odkomentuj "Stos" HashMap - Tablica asocjacyjna (Słownik) Uogólnienie ArrayList w tym sensie, że indeksami mogą być wartości inne niż liczby HashMap<K,V> - dwa parametry: K - typ klucza (indeksu), V - typ wartości elementów kolekcji Przykład: Przyklady.java odkomentuj "Tablica asocjacyjna" Więcej na temat sortowania elementów kolekcji Sortowanie kolekcji obiektów własnej klasy (cz. 1) Przykład: Przyklady.java odkomentuj "Sortowanie obiektów własnej klasy nie powiodło się" 1. Chcemy mieć więcej informacji o miastach: nazwa, ludność, powierzchnia 2. I móc sortować miasta wg nazw (alfabetycznie), ludności (liczbowo), powierzchni (liczbowo) 3. Tworzymy klasę miasto z trzema polami: nazwa, ludnosc, powierzchnia 4. Tworzymy kolekcję ArrayList obiektów klasy miasto (ludność podajemy w tysiącach, powierzchnię w km2) 5. Wczytujemy miasta do kolekcji z pliku. Format pliku: w jednym wierszu nazwa, ludnosc, powierzchnia oddzielone spacją. 6. "Drukujemy" wczytaną kolekcję: System.out.print(miasta). Aby nie drukował się systemowy opis obiektów klasy Miasto tworzymy własny opis obiektu definiując metodę toString w klasie Miasto 7. Wykonanie operacji na wszystkich elementach kolekcji: specjalna postać instrukcji for (można też do zwykłych tablic): for (TypElementowKolekcji Identyfikator: Wyrażenie) Instrukcje; Przykład, wydrukowanie wszystkich elementów kolekcji miasta typu ArrayList for (Miasto s: miasta) System.out.println(s); Sortowanie kolekcji obiektów własnej klasy (cz. 2) 8. Próba posortowania kolekcji obiektów klasy Miasto tak jak wcześniej kolekcji obiektów klasy String: Collections.sort(miasta) nie powiedzie się, kompilator zgłosi błąd 9. Dlaczego błąd: Nie ma zdefiniowanego wg jakiego kryterium porównywać obiekty. W przypadku klas bibliotecznych String i Integer jest zdefiniowane takie kryterium. Obiekty klasy String porównuje się alfabetycznie, Integer liczbowo W naszym przypadku nie ma kryterium jak porównać obiekty klasy Miasto, czy ma to zależeć od ludności czy powierzchni czy nazwy miasta czy jeszcze inaczej. Dlatego sortowanie się nie powiodło. Aby sortowanie obiektów danej klasy się powiodło, klasa musi mieć zdefiniowane kryterium porównawcze. Jak zdefiniować kryterium porównawcze (cz. 1) Zdefiniowanie kryterium porównawczego polega na zaimplementowaniu dla danej klasy interfejsu Comparable: public interface Comparable<T> { public int compareTo(T o); } W dokumentacji czytamy: metoda compareTo zwraca liczbę ujemną całkowitą, zero lub dodatnią całkowitą w zależności czy porównywany obiekt o jest mniejszy (przed), równy, lub większy (po) w stosunku do podanego obiektu. Jak już wspomniano klasa String ma zaimplementowany interfejs Comparable. Więc możemy porównywać obiekty tej klasy za pomocą metody compareTo: Np. "Białystok".compareTo("Wilno") zwróci liczbę ujemną, czyli "Białystok" jest przed "Wilno" Inne przykłady na porównanie: Przyklady.java odkomentuj "Porownania" Zatem metoda sort() porównuje obiekty wywołując metodę compareTo i w ten sposób może posortować obiekty. Jak zdefiniować kryterium porównawcze (cz. 2) Przypadek I: załóżmy, że chcemy sortować obiekty klasy Miasto wg nazw (pole nazwa). Zatem implementując w klasie Miasto interfejs Comparable treść metody compareTo ma być taka, aby zwracała wynik porównania alfabetycznego dwóch nazw. Nazwy są typu String więc nie musimy sami definiować porównania alfabetycznego a skorzystać z metody compareTo klasy String Przypadek II: załóżmy, że chcemy sortować wg liczby ludności (pole ludnosc). Postępujemy analogiczne jak w przypadku I. Wystarczy zmienić implementację metody CompateTo - tym razem ma zwracać wynik porównania liczbowego i również nie musimy sami definiować tego porównania, a skorzystać z metody compareTo klasy Integer Przypadek III: załóżmy, że chcemy sortować wg powierzchni (pole powierzchnia). Postępujemy analogicznie jak w p. II Przykład: Przyklady.java odkomentuj "Sortowanie obiektów klasy Miasto", dla danego przypadku odkomentuj właściwy return w metodzie compareTo i opis z linii 440-442 Metoda sort() - czytanie dokumentacji W dokumentacji nagłówek metody sort jest następujący: public static <T extends Comparable<? super T>> void sort(List<T> list) – Co może być argumentem metody sort: kolekcja List<T> albo klasa potomna lub implementująca dla List<T>. Więc możemy jako argumentu użyć np. obiektu klasy ArrayList<T> – Co może w miejsce parametru T: <T extends Comparable<? super T>> W typach sparametryzowanych słowo "extends" wyjątkowo ma szersze znaczenie. Nie chodzi tu tylko dokładnie o klasę potomną. Może to być również klasa implementująca. Klasa Miasto implementuje Comparable, więc w miejsce T możemy wstawić Miasto. – Co może być argumentem klasy Comparable: obiekt typu T lub obiekt klasy nadrzędnej dla T: Comparable<? super T>. Więc Miasto może być wstawione w miejsce "?" Sortowanie miast - ulepszenie programu (cz. 1) Wada dotychczasowego programu z sortowaniem Miast: • metoda CompareTo może być implementowana raz. Czyli w jednym programie możemy korzystać tylko z jednego rodzaju sortowania. Aby mieć możliwość sortowania wg różnych kryteriów w jednym programie należy skorzystać z przeciążonej wersji metody sort: public static <T> void sort(List<T> list,Comparator<? super T> c) − Drugim argumentem musi być obiekt klasy Comparator, a jego parametrem obiekt typu T lub klasy nadrzędnej dla T − Comparator jest interfejsem z jedną metodą do zaimplementowania: public interface Comparator<T> { int compare(T o1, T o2); } − Z dokumentacji: metoda compare porównuje dwa obiekty o1 i o2. Zwraca ujemną całkowitą, zero lub dodatnią całkowitą w zależności gdy o1 jest mniejszy, równy czy większy od o2 − Tak jak w poprzednim programie metoda sort() korzystała z compareTo(), aby porównać obiekty, tak tutaj przeciążona metoda sort() korzysta z compare() aby zrobić to porównanie Sortowanie miast - ulepszenie programu (cz. 2) Czyli teraz nie implementujemy interfejsu Comparable w klasie Miasto, ale: • definiujemy klasę implementującą interfejs Comparator dla każdego kryterium porównawczego (można jako klasę wewnętrzną). Treść metody compare ma być taka, aby zwracała wynik porównania • obiekt tej klasy podajemy jako argument przeciążonej metody sort Przykład: Przyklady.java odkomentuj "Sortowanie obiektów klasy Miasto ulepszenie"