kolekcji

Transkrypt

kolekcji
Podstawy otwartych języków
programowania
Przechowywanie danych
Wiktor Wandachowicz
Sposoby przechowywania
danych
●
●
●
●
●
Typy podstawowe
Pojedyncze obiekty
Tablice obiektów i tablice typów podstawowych
– jednowymiarowe
– wielowymiarowe
Kolekcje
Inne (serializacja, pliki, zewnętrzne źródła danych)
Typy podstawowe
●
●
●
●
●
●
●
●
●
●
boolean
char
byte
short
int
long
float
double
Tablice
Napisy (String)
●
●
●
●
●
●
●
●
Boolean
Character
Byte
Short
Integer
Long
Float
Double
Równoważne im
obiektowe typy
opakowujące
(ang. wrapper types)
Obiekty
●
●
●
●
Do obiektów odwołujemy się przez uchwyty.
Uchwyty mają znaczenie dla maszyny wirtualnej,
właściwe położenie danych obiektu w pamięci może
się zmieniać.
Uchwyty obiektów, które są “gubione” w programie i
nie są już więcej dostępne są zaznaczane do
usunięcia przez mechanizm odśmiecania pamięci
(ang. garbage collection).
Odśmiecanie pamięci następuje automatycznie.
Tablice
●
Deklaracje tablic:
int[] tablica1;
int tablica2[]; // składnia C/C++, nie zalecane
●
Każdą tablicę przed użyciem trzeba utworzyć lub
zainicjalizować:
char[] symbole = new char[5];
String napisy[] = { "Hello", "world", "!!!" };
●
Każda tablica ma stałe pole length, które
przechowuje ilość jej elementów.
Tablice wielowymiarowe
●
Deklaracje:
double[][] wekt3D = new double[3][3];
●
Używanie – z uwzględnieniem pola length:
for (int i = 0; i < wekt3D.length; i++) {
for (int j = 0; j < wekt3D[i].length; j++) {
System.out.println("wekt3D[" + i + "]" +
"[" + j + "] = " + wekt3D[i][j]);
}
}
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 (Java 1.4)
• Kolekcje znajdują się w pakiecie java.util
• 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. liczby
i pojedyncze litery
• Używając metody size() można odczytać aktualną
ilość elementów w kolekcji
Użycie kolekcji (bez iteratorów)
List zakupy = new ArrayList();
zakupy.add(new Zakup("Mleko"));
zakupy.add(new Zakup("Rogalik");
zakupy.add(new Zakup("Kakao"));
zakupy.add(new Zakup("Miód"));
rozszerzalna tablica
for (int i = 0; i < zakupy.size(); i++) {
System.out.println(i + ". " + zakupy.get(i));
}
Map ceny = new HashMap();
ceny.put("Mleko", new Double(1.69));
ceny.put("Rogalik", new Double(0.45));
odwzorowanie (mapa)
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]));
}
Klasy kolekcji na platformie
Java
Implementacje
Tablica
mieszająca
Set
HashSet
Interfejsy
List
Map
Rozszerzalna
tablica
Zbalansowane
drzewo
TreeSet
ArrayList
HashMap
Lista
wiązana
LinkedList
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 przemieszczanie
się 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ś elementy
w 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
class Krzeslo {
/* ... */
}
Kod działa równie dobrze, jeśli jest:
List sala = new LinkedList();
List sala = new ArrayList();
for (int i = 1; i <= 20; i++) {
sala.add(new Krzesło("nr. " + i));
}
odczyt iteratora
Iterator it = sala.iterator();
czy są jeszcze elementy?
while (it.hasNext()) {
Krzesło k = (Krzesło) it.next();
przywrócenie typu
System.out.println(k.odczytajNumer());
}
(rzutowanie)
• Użycie iteratorów pozwala korzystać z kolekcji w taki
sposób, że łatwo wymienić jej implementację na inną
Dwa sposoby iterowania
//
//
//
//
//
//
z użyciem pętli while – problemy przy cut & paste
1) Nie można mieć dwóch zmiennych w tym samym zakresie
o takiej samej nazwie
2) Zmiana nazwy iteratora – w trzech miejscach
3) Iterator wyczerpany lub konieczność jego reinicjalizacji
Iterator it = sala.iterator();
while (it.hasNext()) {
Krzesło k = (Krzesło) it.next();
System.out.println(k.odczytajNumer());
}
// z użyciem pętli for – bez problemów
for (Iterator it = sala.iterator(); it.hasNext(); ) {
Krzesło k = (Krzesło) it.next();
System.out.println(k.odczytajNumer());
}
Kolekcje w Javie 5 i 6
●
●
●
●
W najnowszej wersji Javy zostały dodane
rozszerzenia języka (m.in. szablony, rozszerzona
pętla for), dzięki którym użycie kolekcji jest
łatwiejsze i mniej podatne na błędy.
Kolekcje zyskały możliwość przechowywania
obiektów ściśle określonego typu.
Iteracja po wszystkich obiektach kolekcji jest o
wiele krótsza w zapisie (brak rzutowań, mniejsza
ilość błędów).
Możliwa jest także iteracja po elementach tablic
korzystając ze składni rozszerzonej pętli for.
Kolekcje w Javie 5 i 6 (c.d.)
●
●
●
Typy uogólnione (ang. generic types) zostały
wprowadzone w Javie zwłaszcza po to, aby już na
etapie kompilacji pozbyć się problemu dodawania
do kolekcji różnego rodzaju danych.
Kolekcje są zgodne binarnie w dół, można więc
m.in. korzystać w skompilowanym kodzie
(biblioteki) z nowych kolekcji.
Odbywa się to przez mechanizm wymazywania
(ang. erasure) – „magię kompilatora”.
Cechy kolekcji (Java 5 i 6)
• Kolekcje znajdują się w pakiecie java.util
• Kolekcje przechowują referencje do wskazanego typu
danych, przy użyciu typów uogólnionych
• W jednej kolekcji mogą być obiekty jedynie wskazanej
klasy oraz jej klas pochodnych
• Przy odczycie elementów odtwarzany jest odpowiedni
typ danych (nie jest potrzebne rzutowanie)
• Liczby i pojedyncze litery można umieszczać wprost w
kolekcjach przez użycie mechanizmu autoboxing
• Używając metody size() można odczytać aktualną
ilość elementów w kolekcji
Kolekcje w nowym stylu
public class Klasa {
private String napis;
public Klasa(String parametr) {
this.napis = parametr;
}
public String toString() {
return "Klasa(" + napis + ")";
}
}
// kolekcja uwzględniająca typ danych
List<Klasa> dane = new LinkedList<Klasa>();
for (int i = 1; i <= 7; i++) {
dane.add(new Klasa("obiekt_" + i));
}
// iterator uwzględniający typ danych
Iterator<Klasa> it = dane.iterator();
while (it.hasNext()) {
Klasa obiekt = it.next(); // nie ma rzutowania!
System.out.println(obiekt);
}
Trzy sposoby iterowania
// z użyciem pętli while – problemy przy cut & paste
Iterator<Klasa> it = dane.iterator();
while (it.hasNext()) {
Klasa obiekt = it.next();
System.out.println(obiekt);
}
// z użyciem pętli for – bez problemów
for (Iterator<Klasa> it = dane.iterator(); it.hasNext(); ) {
Klasa obiekt = it.next();
System.out.println(obiekt);
}
// z użyciem rozszerzonej pętli for
// (przykład równoważny poprzedniej pętli)
for (Klasa obiekt : dane) {
System.out.println(obiekt);
}
Stare kolekcje w nowym
wydaniu
// RÓŻNE TYPY DANYCH W JEDNEJ KOLEKCJI
// Kolekcja przechowująca elementy typu Object
List tradycyjna = new Vector();
// operacja poprawna
tradycyjna.add(new Integer(5));
// autoboxing
tradycyjna.add(6);
// Poniższy kod kompiluje się, ale pojawia się błąd
// w trakcie działania programu
/* tradycyjna.add(new Klasa("obiekt")); */
// Nowy sposób iterowania po starej kolekcji
for (Object o : tradycyjna) {
// unboxing: Object -> Integer -> int
int x = (Integer) o;
System.out.println(o.getClass().getName() + " | " + x);
}
Odwzorowania (mapy)
w nowym stylu
// AUTOBOXING I UNBOXING W PRAKTYCE
// odwzorowanie uwzględniające wskazany typ klucza i wartości
Map<String,Double> ceny = new HashMap<String,Double>();
ceny.put("Mleko", new Double(1.69));
// autoboxing: automatyczna konwersja double -> Double
ceny.put("Rogalik", 0.45);
System.out.println("Ceny produktów:");
for (String produkt : ceny.keySet()) {
System.out.println(produkt + "\t\t" + ceny.get(produkt));
}
System.out.print("Zakup po jednej sztuce to wydatek: ");
double suma = 0.0; // też dobrze dla: Double suma = 0.0;
for (String produkt : ceny.keySet()) {
// unboxing Double -> double przed sumowaniem
suma += ceny.get(produkt);
}
System.out.println(suma);

Podobne dokumenty