290 likes | 457 Views
Kolekcje. Cechy kolekcji Przegląd interfejsów i klas kolekcji Przykłady użycia Iteratory. Cechy kolekcji. Kolekcje w Javie przechowują grupy obiektów, wykorzystując gotowe algorytmy składowania danych.
E N D
Kolekcje • Cechy kolekcji • Przegląd interfejsów i klas kolekcji • Przykłady użycia • Iteratory
Cechy kolekcji Kolekcje w Javie przechowują grupy obiektów,wykorzystując gotowe algorytmy składowania danych • Siła kolekcji leży w tym, że są zamienne – mają taki sam interfejs, a różnią się implementacją • Są dwa podstawowe interfejsy: Collection i Map,inne interfejsy są ich rozszerzeniem • Platforma Java zawiera różne implementacje tych samych interfejsów • Każdą kolekcję obiektów można przejść z użyciem iteratora (uniwersalnie), lub w przewidziany tylko dla niej sposób (specyficznie)
Interfejsy kolekcji • Kolekcja (Collection) reprezentuje grupę obiektów (elementów) • Zbiór (Set) jest kolekcją która nie może zawierać powtórzeń elementów • Lista (List) jest kolekcją z ustalonym porządkiem (kolejnością) elementów, może zawierać powtórzenia • Odwzorowanie (Map) przyporządkowuje do danych kluczy wartości, klucze nie mogą się powtarzać
Cechy kolekcji (c.d.) • Kolekcje przechowują referencje do Object, nie są więc czułe na typ danych (gubią informację o typie) • Przy odczycie elementów trzeba wykonywać rzutowanie do odpowiedniego typu danych • W jednej kolekcji mogą być obiekty różnych klas (ponieważ wszystkie są zgodne z Object) • Używając typów opakowujących (ang. wrapper types) można umieszczać w kolekcjach m.in. liczbyi pojedyncze litery • Używając metody size() można odczytać aktualną ilość elementów w kolekcji • Kolekcje znajdują się w pakiecie java.util
Użycie kolekcji List zakupy = new ArrayList(); zakupy.add("Mleko"); zakupy.add("Rogalik"); zakupy.add("Kakao"); zakupy.add("Miód"); for (int i = 0; i < zakupy.size(); i++) { System.out.println(i + ". " + zakupy.get(i)); } rozszerzalna tablica Map ceny = new HashMap(); ceny.put("Mleko", new Double(1.49)); ceny.put("Rogalik", new Double(0.45)); System.out.println("Cena rogalika: " + ceny.get("Rogalik")); Object[] produkty = ceny.keySet().toArray(); for (int j = 0; j < produkty.length; j++) { System.out.println( produkty[j]+" : " + ceny.get(produkty[j])); } odwzorowanie (mapa)
Klasy kolekcji na platformie Java Implementacje Tablicamieszająca Rozszerzalna tablica Zbalansowane drzewo Lista wiązana Interfejsy Set HashSet TreeSet List ArrayList LinkedList Map HashMap TreeMap
Klasy kolekcji (c.d.) • Najprostszą klasą kolekcji jest ArrayList (jest to lista zaimplementowana w postaci tablicy). Zapewnia ona szybki dostęp swobodny do elementów i potrafi automatycznie powiększać swój rozmiar. W starej bibliotece kolekcji jej odpowiednikiem jest Vector. • Większą funkcjonalność posiada klasa LinkedList (jest to lista o szybkim dostępie sekwencyjnym do elementów). Także automatycznie powiększa swój rozmiar. Jest jednak stosunkowo powolna przy dostępie swobodnym. Posiada bardziej uniwersalny zestaw metod (np. addFirst() / addLast()).
Przegląd metod kolekcji • Wybrane metody interfejsu Collection: • dodanie elementów – metoda add() • odczyt ilości elementów – metoda size() • pobranie elementu – metoda get() • ustawienie elementu – opcjonalna metoda set() • usunięcie elementu – opcjonalna metoda remove() • zwrócenie tablicy z elementami kolekcji – metoda toArray() • Wybrane metody interfejsu Map: • dołączenie elementu do klucza – metoda put() • odczytanie elementu spod klucza – metoda get() • odczyt zbioru wszystkich kluczy – metoda keySet() • test czy klucz jest w kolekcji – metoda containsKey() • test czy element jest w kolekcji – metoda containsValue()
Iteratory Iterator jest obiektem umożliwiającym przemieszczaniesię po elementach kolekcji, niezależnie od jej struktury • Obiekt iteratora dla kolekcji uzyskuje się wywołując jej metodę iterator(). Jest on gotów do zwrócenia pierwszego elementu ciągu. • Dla uzyskania następnego elementu kolekcji należy wywołać metodę next() iteratora. • Można sprawdzić, czy są jeszcze jakieś elementyw ciągu wywołując metodę hasNext() • Można usunąć ostatni zwrócony przez iterator element, stosując metodę remove()
Przykład użycia iteratora Kod działa równie dobrze, jeśli jest: List sala = new LinkedList(); odczyt iteratora czy są jeszcze elementy? przywrócenie typu (rzutowanie) class Krzeslo { /* ... */ } List sala = new ArrayList(); for (int i = 1; i <= 20; i++) { sala.add(new Krzeslo("nr. " + i)); } Iterator it = sala.iterator(); while (it.hasNext()) { Krzeslo k = (Krzeslo) it.next(); System.out.println(k.odczytajNumer()); } • Użycie iteratorów pozwala korzystać z kolekcji w taki sposób, że łatwo wymienić jej implementację na inną
Wyjątki Podstawą filozofii Javy jest założenie, że:źle sformułowany kod nie zostanie wykonany • Sytuacja błędna powoduje utworzenie nowego obiektuwyjątku i rzucenie go • Kod, który wyrzuca wyjątki można spróbować wykonać,a pojawiające się wyjątki można łapać • Złapany wyjątek można obsłużyć albo rzucić ponownie • Jeśli kod w metodzie rzuca wyjątek (nie jest on obsłużony), musi być to wyspecyfikowane w deklaracji metody • Wszystkie wyjątki pochodzą od klasyjava.lang.Exception
Łapanie wyjątków • Odbywa się z użyciem bloków try i catch. • Pierwszy blok (try – spróbuj) obejmuje kod, który może spowodować wyjątek. • Drugi blok (catch – złap) określa jakie wyjątki chce obsłużyć i zawiera kod z obsługą błędów. • Jeśli wyjątek został złapany, można m.in. • wyświetlić informację o pochodzeniu błędu (jest to najczęściej używane): e.printStackTrace() • odczytać komunikat błędu: e.getMessage() • odczytać źródło błędu: e.getCause()
Łapanie wyjątków – przykład (1) blok try lokalna obsługa wyjątku import java.io.*; public class Imie { static void odczytajImie() { BufferedReader in = new BufferedReader( new InputStreamReader(System.in)); try { System.out.print("Podaj imie: "); String imie = in.readLine(); // może być wyjątek System.out.print("Witaj " + imie + "!"); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { odczytajImie(); } }
Łapanie wyjątków – przykład (2) specyfikacja wyjątku blok try obsługa wyjątku import java.io.*; public class Imie { static void odczytajImie() throws IOException { BufferedReader in = new BufferedReader( new InputStreamReader(System.in)); System.out.print("Podaj imie: "); String imie = in.readLine(); // może być wyjątek System.out.print("Witaj " + imie + "!"); } public static void main(String[] args) { try { odczytajImie(); } catch (IOException e) { e.printStackTrace(); } } }
Rzucanie wyjątków • Aby zasygnalizować błąd, należy utworzyć obiekt wyjątku (podając przyczynę błędu) • Następnie należy rzucić wyjątek, z użyciem słowa kluczowego throw: long suma = 0; int iloscNieujemnych = 0; void dodajNieujemna(int liczba) throws IllegalArgumentException { if (liczba > 0) { suma += liczba; iloscNieujemnych++; } else throw new IllegalArgumentException("liczba <= 0"); }
Tworzenie własnych klas wyjątków • Nowa klasa wyjątku powinna dziedziczyć z Exception • Powinna deklarować przynajmniej dwa konstruktory: • bezparametrowy • z jednym argumentem typu String • Może zawierać dodatkowe pola i metody public class AccessDeniedException extends Exception { public AccessDeniedException() { super(); } public AccessDeniedException(String s) { super(s); } }
Strumienie wejścia/wyjścia • Typy strumieni • Łączenie strumieni dla zwiększenia możliwości • Różne źródła i ujścia danych • Przykłady użycia
Strumienie danych Strumień jest abstrakcyjną reprezentacją dowolnego źródła lub ujścia danych • Na podstawie dwóch logicznych operacji wyróżniamy dwa typy strumieni: • strumienie wejściowe (odczyt danych) • strumienie wyjściowe (zapis danych) • Strumień jest zawsze stowarzyszony z jakimśźródłem danych (odczyt) lub ujściem (zapis) • Wyróżniamy także strumienie bajtowe i znakowe • W Javie obsługę strumieni zapewnia pakiet java.io
Strumienie wejściowe i wyjściowe strumień wejściowy źródłodanych odczyt informacja Program strumień wyjściowy zapis ujściedanych Program informacja
Algorytmy odczytu i zapisu Algorytmy odczytu i zapisu otwórz strumień jeśli jest jeszcze informacja odczytaj informację zamknij strumień Odczyt otwórz strumień jeśli jest jeszcze informacja zapisz informację zamknij strumień Zapis
Hierarchia strumieni Strumienie bajtowe Strumienie znakowe • Klasy strumieni są w pakiecie java.io • Przy nieudanych operacjach pojawiają się wyjątki klasy java.io.IOException • Strumienie bajtowe i znakowe zapewniają praktycznie taką samą funkcjonalność
Strumienie bajtowe • Dwa najbardziej ogólne strumienie bajtowe to: • InputStream – do odczytu, oraz • OutputStream – do zapisu ciągów bajtów.
Strumienie znakowe • Podstawowymi strumieniami znakowymi są: • Reader – do odczytu, oraz • Writer – do zapisu ciągów znaków.
Rozszerzanie funkcjonalności • Zwiększenie funkcjonalności odbywa się przez użycie wyspecjalizowanych strumieni. Korzystają onez innych strumieni, aby wykonywać swoją pracę. • Robi się to przez opakowanie jednego typu strumienia w inny (aby to zadziałało musi istniećw wybranej klasie odpowiedni konstruktor). BufferedReader String readLine() InputStreamReader int read(char[] cbuf) InputStream int read(byte[] b)
Odczyt standardowego wejścia InputStream import java.io.*; public class PowielajLinie { public static void main(String[] args) throws IOException { System.out.println("Wpisuj linie tekstu. " + "Koniec gdy pusta linia."); } } BufferedReader in = new BufferedReader( new InputStreamReader(System.in)); new InputStreamReader(System.in) System.in String linia; do { linia = in.readLine(); System.out.println(linia); } while (linia.length() > 0);
Strumienie wyspecjalizowane • Zamiana strumieni bajtowych na znakowe: • InputStreamReader / OutputStreamWriter • Odczyt i zapis z uwzględnieniem znaków końca linii: • BufferedReader– readLine() • BufferedWriter– newLine() • Strumień z buforem (większa wydajność): • BufferedInputStream / BufferedOutputStream • Przeciążone metody println(): • PrintStream / PrintWriter
Strumienie wyspecjalizowane • Odczyt i zapis tablic bajtów lub znaków (w pamięci): • ByteArrayInputStream / ByteArrayOutputStream • CharArrayReader / CharArrayWriter • Odczyt i zapis łańcuchów napisów (w pamięci): • StringReader / StringWriter • Odczyt i zapis plików: • FileInputStream / FileOutputStream • FileReader / FileWriter • Serializacja obiektów: • ObjectInputStream / ObjectOutputStream
Odczyt i zapis plików • Żeby otworzyć plik, wystarczy stworzyć obiekt wybranej klasy, podając nazwę pliku w postaci łańcucha znaków lub obiektu klasy File • FileInputStream – odczyt pliku binarnego • FileOutputStream – zapis pliku binarnego (*) • FileReader – odczyt pliku znakowego • FileWriter – zapis pliku znakowego (*) (*) możliwe otwarcie pliku do dopisywania, bez usuwania poprzedniej zawartości • Otwarty strumień można opakować w wybrany strumień wyspecjalizowany • Po zakończeniu strumień należy zamknąć – close()
Klasa File • NIE JEST to plik – służy raczej jako OPIS ŚCIEŻEK do plików lub katalogów: • Przy użyciu tej klasy można także m.in. • sprawdzać informacje o pliku: isDirectory(), isFile(), canRead(), canWrite(), exists(), length(), lastModified() • wykonywać operacje na plikach i katalogach: (delete(), mkdir(), mkdirs(), renameTo() • odczytywać zawartość katalogu: list(), listFiles() File plik = new File("plik.txt"); FileReader in = new FileReader(plik);