Transcript Kolekcje

BJUG_1: Typy Generyczne, Kolekcje
Wszystko co warto wiedzieć… w pracy i na rozmowie
kwalifikacyjnej
Agenda
 Typy Generyczne
•
Czym są Typy Generyczne i dlaczego warto ich używać
•
Zastosowanie Typów Generycznych
•
WildCards – opis wykorzystania słów kluczowych extends\super przy deklaracji typów
generycznych
•
Procesu wymazywania typów - jak działa kompilator w Javie
•
Implemenacja Pary przy wykorzystaniu Typów Generycznych
 Kolekcje
•
Wstęp do JCF
•
…Hash, hashCode
•
Struktura frameworka
•
Opis najważniejszych klas i funkcjonalności
•
Collection VS Collections
Typy Generyczne - Wprowadzenie
• Koncept programowania generycznego został nakreślony w 1988 roku przez Davida
Mussera (programista C++) i Alexandra Stepanova (C++ designer) :
“Generic programming is about abstracting
and classifying algorithms and data
structures. […] Its goal is the incremental
construction of systematic catalogs of useful,
efficient and abstract algorithms and data
structures.”
Typy Generyczne - Czym są Typy Generyczne i dlaczego warto ich używać
• Java jest językiem ściśle typowanym – do referencji o danym typie możemy przypisać
jedynie obiekty tego typu, bądź typów pochodnych
• Generyki dostarczają dodatkową warstwę abstrakcji ponad standardowymi Typami
•
Klasy, Interfejsy oraz Metody mogą być sparametryzowane przez dowolny typ
•
Posłużmy się przykładem ArrayList’y: public class ArrayList<E> ...
•
Podczas inicjalizacji obiektu ArrayList za <E> należy podstawić dowolony, konkretny typ
•
List<String> list = new ArrayList<String>(); ( < 1.7)
•
List<String> list = new ArrayList<>(); (1.7)
• Dodatkowo, wykorzystanie Typów Generycznych podnosi czytelność kodu oraz ułatwia
proces inżynierii wstecznej (gdy już przywyknie się do składni )
• Umożliwia pisanie generycznych algorytmów
Typy Generyczne – Największa zaleta
• Problem: Istnieje niesparametryzowana Kolekcja obiektów
•
Kompilator nie jest w stanie odgadnąć typu obiektów
•
Programista podczas pobierania obiektów z Kolekcji zmuszony jest dokonywać castowania
•
Wyjątek ClassCastException może zostać zgłoszony w trakcie pracy programu (runtime
exception)
• Rozwiązanie: wykorzystanie Typów Generycznych
•
Określą typ obiektów w Kolekcji
•
Kompilator dokona castowania
•
Przykład: Kompilator sprawdzi czy programista nie próbuje dodać Integer’a do listy String’ów
i zgłosi ewentualny błąd w czasie kompilacji
Typy Generyczne - Wildcards
• Przypuśćmy, że chcemy napisać metodę która wypisze wszystkie elementy z Kolekcji,
przykładowy kod w wersjach Javy < 1.5 mógłby wyglądać:
public static void printCollection(Collection collection) {
Iterator iterator = collection.iterator();
for (int i = 0; i < collection.size(); i++) {
System.out.println(iterator.next());
}
}
Typy Generyczne - Wildcards
• Zastosowanie Typów Generycznych – podejście pierwsze
public static void printCollection(Collection<Object> collection) {
for (Object o : collection) {
System.out.println(o);
}
}
• Wykorzystanie metody:
public static void main(String[] args) {
Collection<String> cs = new Vector<String>();
printCollection(cs); // Błąd kompilacji
List<Integer> li = new ArrayList<Integer>(10);
printCollection(li); // Błąd kompilacji
}
Typy Generyczne - Wildcards
• Zastosowanie Typów Generycznych – podejście drugie
public static void printCollection(Collection<? extends Object> c) {
for (Object o : c) {
System.out.println(o); // Brak błędu, ale zabronione jest dodawanie obiektów
}
}
• Wykorzystanie metody:
public static void main(String[] args) {
Collection<String> cs = new Vector<String>();
printCollection(cs); // Brak błędu
List<Integer> li = new ArrayList<Integer>(10);
printCollection(li); // Brak błędu
}
•
Co zrobić w przypadku gdy zależy nam na dodawaniu obiektów do Kolekcji?:
public static void printCollection(Collection<? super Integer> c)
Typy Generyczne – Wymazywanie typów
• Typy Generyczne wykorzystują proces wymazywania
•
Parametry typów są usuwane z klas w procesie kompilacji
• Proces ten został wymuszony przez chęć zachowania wstecznej kompatybilności z
wersjami Javy < 1.5
• Po usunięciu zapisu generycznego na jego miejsce kompilator wstawia castowanie
Typy Generyczne – Wymazywanie typów
Source File
Type
Annotation Class File
Checker Checker
Writer
Parser
class Pi {
double pi;
@GoRMI
Object getPi() {
return field;
}
@Override
public String
toString(){
return „” + pi;
}
}
Program
with
annotations
Error
Error
Annotation
Checker
Plugins
Typy Generyczne – Przykład zastosowania
public class Pair<A, B> {
private A elementA;
private B elementB;
public Pair(A elementA, B elementB) {
this.elementA = elementA;
this.elementB = elementB;
}
public A getElementA() {
return elementA;
}
public void setElementA(A elementA) {
this.elementA = elementA;
}
public B getElementB() {
return elementB;
}
public void setElementB(B elementB) {
this.elementB = elementB;
}
}
Typy Generyczne – Kiedy używać?
• Wtedy gdy potrzebujemy zapewnić bezpieczeństwo na operacjach typów i uniknąć
castowania – czyli zawsze
• Podczas implementacji generycznych algorytmów, klas typu Utilities
Kolekcje – Wstęp do JCF
• API Javy dostarcza gotowe implementacje
najczęściej używanych w programowaniu struktur
danych
• Struktury te w nomenklaturze Javy nazywamy
Kolekcjami
• Rozumiemy je zaś jako Obiekty przechowywujące
inne Obiekty
• Java Collections Framework pozwala więc
reprezentować i manipulować w różnorodny
sposób grupami obiektów
• Framework składa się z Interfejsów oraz
implementujących je Klas
Kolekcje – …Hash, hashCode, equals
• Znajomość działania metod equals oraz hashCode jest potrzebna do zrozumienia dziania
niektórych kolekcji
• W Javie metody equals oraz hashCode dziedziczone są z klasy object
• Sygnatury metod to:
•
•
public boolean equals(Object obj)
public int hashCode()
• Metoda equals sprawdza czy obiekty są takie same (co sprawdza == ?) – odpowiedź na
pytanie czy obiekty są takie same należy do implementującego metodę
• Dodatkowo aby poprawnie zaimplementować equals , należy przestrzegać kontraktu. Jego
warunki mowią że relacja wyznaczona metodą equals musi być:
•
•
•
•
Zwrotna
Symetryczna
Przechodnia
Wywołanie metody equals z argumentem null musi zwrócić false
Kolekcje – …Hash, hashCode, equals
•
•
Kontrakt metody hashCode:
•
Każdorazowe uruchomienie metody hashCode na danych obiektach musi zwracać te same wartości
•
Jeśli dwa obiekty są takie same (equals zwraca true), muszą mieć taką samą wartość zwracaną przez
metodę hashCode
Equals i hashCode w kolekcjach:
Kolekcje – Interfejsy
Iterable
Map
Collection
Set
SortedSet
NavigableSet
List
Queue
SortedMap
Deque
NavigableMap
Kolekcje – Mapy – Metody
•
•
•
•
•
•
•
•
void clear()
boolean containsKey(Object key)
Set<Map.Entry<K,V>> entrySet()
V get(Object key)
V put(K key, V value)
V remove(Object key)
int size()
Set<K> keySet()
Map
•
•
K firstKey()
K lastKey()
SortedMap
NavigableMap
•
•
•
SortedMap<K,V> headMap(K toKey)
SortedMap<K,V> tailMap(K fromKey)
SortedMap<K,V> subMap(K fromKey, K toKey)
Kolekcje – Interfejsy
•
•
boolean add(E e)
•
boolean remove(Object o)
•
Object[] toArray()
Iterator<T> iterator()
Iterable
Collection
Set
SortedSet
NavigableSet
List
Queue
Deque
Kolekcje – Interfejsy
Iterable
Collection
List
Set
SortedSet
NavigableSet
Queue
Deque
•
•
void add(int index, E element)
List<E> subList(int fromIndex,
int toIndex)
Kolekcje – Interfejsy
Iterable
•
E ceiling(E e)
•
E floor(E e)
•
NavigableSet<E> tailSet(E fromElement, boolean
inclusive)
•
NavigableSet<E> headSet(E toElement, boolean
inclusive)
Collection
List
Set
SortedSet
NavigableSet
Queue
Deque
•
E first()
•
E last()
•
SortedSet<E> headSet(E toElement)
•
SortedSet<E> subSet(E fromElement, E toElement)
•
SortedSet<E> tailSet(E fromElement)
Kolekcje – Interfejsy
Iterable
•
boolean offer(E e)
•
E poll()
•
E peek()
Collection
List
Set
SortedSet
NavigableSet
Queue
Deque
•
E getFirst()
•
E getLast()
•
E peekFirst()
•
E peekLast()
Kolekcje - ArrayList
• Tablica o zmiennym rozmiarze, ulegająca automatycznemu powiększeniu lub
zmniejszeniu podczas dodawania i usuwania obiektów
• Wewnątrz klasy rolę kontenera na obiekty pełni tablica obiektów
• ArrayList’a zastąpiła klasę Vector – różnica – metody klasy Vector są zsynchronizawane
• Można dodawać null
Kolekcje – ArrayList – podstawowe operacje
//inicjalizacja
List<String> stringList = new ArrayList<String>();
//dodawanie elementów
stringList.add("Element One");
stringList.add(null);
//pobieranie elementów
String a = stringList.get(0);
//usuwanie
stringList.remove(0);
//iteracja pętlą for each
for (String s : stringList) {
System.out.println(s);
}
Kolekcje – ArrayList VS LinkedList
• LinkedList jest kolejną implementacją interfejsu List, opartą o dostęp wiązany (previous,
next)
ArrayList
LinkedList
szybszy dostęp do poszczególnych
elementów (indeksy)
szybsze operacje dodawania i
usuwania
Aby dodać element wykonywana
jest operacja tworzenia nowej
tablicy
Aby dodać element wystarczy
odpowiednio ustawić referencje
Kolekcje – HashSet, TreeSet
• Klasy obiektów umieszczanych w HashSet’cie muszą implementować metody equals oraz
hashCode
• Dostęp do obiektów przyśpieszony dzięki funkcji haszującej
• Obiekty w HashSet’cie są unikalne – duplikaty nie będą dodawane do kolekcji
• Może przyjąć null’a
• Obiekty w omawianej kolekcji nie są indeksowane, niemożliwy więc jest dostęp
numeryczny
• Obiekty dodawane do TreeSet’u muszą implementować Comparable\Comparator
• Obiekty w TreeSet’cie są sortowane (porządek naturalny - Comparable)
Kolekcje – HashSet, TreeSet – podstawowe operacje
//inicjalizacja
Set<String> stringSet = new HashSet<String>();
//dodawanie elementów
String element = "Element One";
stringSet.add(element);
stringSet.add(null);
//sprawdzanie zawierania obiektów
boolean isElement = stringSet.contains(element);
//usuwanie
stringSet.remove(element);
//iteracja pętlą for each
for (String s : stringSet) {
System.out.println(s);
}
Kolekcje – HashMap, TreeMap
• Służą przechowywaniu obiektów w parach klucz – wartość
• Analogicznie jak w przypadku HashSet’u obiekty dodawane do HashMap’y jako klucze
muszą mieć poprawnie zaimplementowane metody equals oraz hashCode
• Dostęp do obiektów przechowywanych kolekcji uzyskuje się poprzez wartość klucza
• Klucz musi pozostać unikalny dla obiektu kolekcji
• Dozwolone jest dodawanie null’a jako klucz oraz wartość
• Klasy obiektów dodawanych do TreeMap’y muszą implementować Comparable lub
Comparator
• Obiekty w TreeMap’ie posortowane są po kluczach (porządek naturalny - Comparable)
Kolekcje – HashMap, TreeMap – podstawowe operacje
//inicjalizacja
Map<Integer, String> map = new HashMap<Integer, String>();
//dodawanie elementów
map.put(1, "One");
map.put(null, null);
//pobieranie elementów
String value = map.get(1);
//usuwanie
String removedvalue = map.remove(1);
//iteracja pętlą for each
for (Integer i : map.keySet()) {
System.out.println(map.get(i));
}
Kolekcje – PriorityQueue
• Elementy dodawane do PriorityQueue są sortowane w porządku naturalnym
• Nie można dodać null’a
• Pierwszym elementem w kolejce jest zawsze „najmniejszy” obiekt zgodnie z przyjętym
porządkiem sortowania
• Dozwolone dodawanie obiektów o tej samej wartości
• Metoda poll zwraca i usuwa pierwszy obiekt w kolejce
• Metoda peek zwraca lecz nie usuwa pierwszy obiekt w kolejce
• Jeśli kolejka jest pusta zostanie zwrócony null
• Do dodawania obiektów do kolejki służy metoda offer
Kolekcje – PriorityQueue – podstawowe operacje
PriorityQueue<Integer> a = new PriorityQueue<>();
// inicjalizacja
PriorityQueue<Integer> queue = new PriorityQueue<>();
// dodawanie elementów
queue.offer(1);
queue.offer(2);
queue.offer(2);
// pobieranie pierwszego elementu bez usuwania
int peek = queue.peek();
// pobieranie pierwszego elementu z usuwaniem
int poll = queue.poll();
// iteracja pętlą for each
for (Integer i : queue) {
System.out.println(i);
}
Kolekcje – Collection VS Collections
• Poza Kolekcjami Java udostępnia także klasę Collections, która jest zbiorem statycznych
metod zawierających implementacje najczęściej wykorzystywanych operacji
algorytmicznych
• Najważniejsze z metod dostępnych w klasie Collections to:
•
public static <T extends Comparable<? super T>> void sort(List<T> list)
•
public static <T> void sort(List<T> list, Comparator<? super T> c)
•
public static void reverse(List<?> list)
•
public static <T extends Object & Comparable<? super T>> T min(Collection<
? extends T> coll)
•
public static <T extends Object & Comparable<? super T>> T max(Collection<
? extends T> coll)
www.tt.com.pl