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"