1. Czym jest interfejs Collection
W Java interfejs to jak umowa: jeśli klasa implementuje interfejs, jest zobowiązana dostarczyć implementację wszystkich jego metod. Sam interfejs nie przechowuje stanu i nie zawiera kodu (prawie: od Java 8 możliwe są metody default, ale teraz ważna jest podstawowa idea).
Collection — bazowy interfejs dla większości kolekcji w Java. Określa, co kolekcja potrafi: dodawać elementy, usuwać, poznawać rozmiar, sprawdzać obecność elementów itp.
public interface Collection<E> extends Iterable<E> {
int size();
boolean isEmpty();
boolean contains(Object o);
boolean add(E e);
boolean remove(Object o);
void clear();
Iterator<E> iterator();
// ... i jeszcze mnóstwo przydatnych metod
}
Kluczowe metody:
- add(E e) — dodać element.
- remove(Object o) — usunąć element.
- size() — poznać liczbę elementów.
- isEmpty() — sprawdzić, czy kolekcja jest pusta.
- contains(Object o) — sprawdzić obecność elementu.
- clear() — wyczyścić kolekcję.
- iterator() — pobrać iterator do iteracji.
Dlaczego Map nie dziedziczy po Collection?
Map stoi osobno wśród kolekcji. Ponieważ Map to zbiór par „klucz → wartość”, a nie po prostu zbiór elementów. Ma inny kontrakt i inny zestaw metod. Na przykład w Map nie ma metody add, ponieważ dodawanie odbywa się przez put(key, value), i nie ma sensu sprawdzać obecności wartości bez znajomości klucza.
2. Hierarchia kolekcji
Wyobrażone „drzewo” głównych interfejsów wygląda tak:
Iterable
|
Collection
/ | \
List Set Queue
|
Deque
- Iterable — najbardziej podstawowy interfejs: wszystko, po czym można iterować w pętli for-each.
- Collection — rozszerza Iterable, dodaje operacje pracy z kolekcją elementów.
- Trzy główne gałęzie:
- List — uporządkowana lista, dopuszcza duplikaty.
- Set — zbiór unikalnych elementów, kolejność zależy od implementacji.
- Queue — kolejka (zwykle FIFO); podtyp — Deque (kolejka dwukierunkowa).
A Map żyje osobno:
Map
/ \
HashMap TreeMap
Wizualizacja hierarchii (schemat)
+--------------------+
| Iterable<E> |
+--------------------+
|
+--------------------+
| Collection<E> |
+--------------------+
/ | \
+--------+ +-------+ +-------+
| List | | Set | | Queue |
+--------+ +-------+ +-------+
|
+------+
|Deque |
+------+
+--------------------+
| Map<K,V> |
+--------------------+
3. List: uporządkowana kolekcja z duplikatami
List — to kolekcja, w której:
- Ważna jest kolejność elementów (pierwszy, drugi, trzeci…).
- Dopuszczalne są takie same elementy (duplikaty).
- Można pobrać element po indeksie (list.get(2)), zamienić go, wstawić w dowolne miejsce.
Przykłady implementacji: ArrayList — szybki dostęp po indeksie; LinkedList — dobry przy częstych wstawkach/usunięciach w środku.
import java.util.*;
List<String> shoppingList = new ArrayList<>();
shoppingList.add("Mleko");
shoppingList.add("Chleb");
shoppingList.add("Ser");
shoppingList.add("Chleb"); // Duplikaty są dozwolone!
System.out.println(shoppingList.get(1)); // "Chleb"
Typowe metody List:
- add(E e), add(int index, E e)
- get(int index), set(int index, E e)
- remove(int index), remove(Object o)
- indexOf(Object o), lastIndexOf(Object o)
4. Set: zbiór unikalnych elementów
Set — to kolekcja, w której:
- Każdy element jest unikalny (brak duplikatów).
- Kolejność przechowywania nie jest gwarantowana w HashSet, może być sortowanie w TreeSet lub kolejność wstawiania w LinkedHashSet.
Przykłady implementacji: HashSet, TreeSet, LinkedHashSet.
import java.util.*;
Set<String> uniqueNames = new HashSet<>();
uniqueNames.add("Ania");
uniqueNames.add("Borys");
uniqueNames.add("Ania"); // Nie zostanie dodane — już istnieje!
System.out.println(uniqueNames.contains("Ania")); // true
System.out.println(uniqueNames.size()); // 2
Typowe metody Set:
- add(E e), remove(Object o)
- contains(Object o)
- size(), isEmpty()
5. Map: kolekcja par klucz–wartość
Map — to kolekcja, w której:
- Każdy element to para klucz → wartość.
- Klucze są unikalne, wartości mogą się powtarzać.
- Szybki dostęp po kluczu.
Przykłady implementacji: HashMap, TreeMap, LinkedHashMap.
import java.util.*;
Map<String, String> phoneBook = new HashMap<>();
phoneBook.put("Ania", "+19991112233");
phoneBook.put("Borys", "+19994445566");
phoneBook.put("Ania", "+19990001122"); // Nadpisze numer Ani!
System.out.println(phoneBook.get("Ania")); // "+19990001122"
System.out.println(phoneBook.containsKey("Borys")); // true
Typowe metody Map:
- put(K key, V value), get(K key)
- remove(K key)
- containsKey(K key), containsValue(V value)
- keySet(), values(), entrySet()
6. Wizualizacja hierarchii: wszystko na jednym obrazku
Krótka tabela zbiorcza:
| Interfejs | Opis | Przykłady implementacji | Kluczowe cechy |
|---|---|---|---|
|
Uporządkowana lista | |
Dostęp po indeksie, duplikaty |
|
Zbiór unikalnych wartości | |
Wyłącznie unikalne elementy |
|
Pary klucz–wartość | |
Klucze unikalne, wartości dowolne |
Hierarchia na schemacie:
Collection
/ | \
List Set Queue
|
Deque
Map (oddzielnie)
7. Kiedy używać którego interfejsu
List
- Gdy ważny jest porządek elementów (np. historia działań użytkownika).
- Gdy potrzebne są duplikaty (np. pozycje zamówienia).
- Gdy potrzebny jest szybki dostęp/podmiana po indeksie.
Set
- Gdy potrzebna jest unikalność (email, loginy, id).
- Gdy kolejność nie jest istotna albo przeciwnie — potrzebny jest automatycznie posortowany zbiór (TreeSet).
Map
- Gdy trzeba kojarzyć klucze i wartości (id → obiekt, login → profil).
- Gdy potrzebne jest szybkie wyszukiwanie po kluczu.
- Gdy klucze mają być unikalne, a wartości — niekoniecznie.
8. Typowe błędy przy pracy z hierarchią kolekcji
Błąd nr 1: Użycie niewłaściwego interfejsu w deklaracji zmiennej. Jeśli piszesz ArrayList<String> list = new ArrayList<>();, twardo wiążesz się z implementacją. Lepiej List<String> list = new ArrayList<>(); — łatwiej wtedy podmienić implementację.
Błąd nr 2: Próba dodania duplikatów do Set i oczekiwanie, że się pojawią. To nie błąd, a cecha: Set z definicji nie przechowuje duplikatów. Powtórne wstawienie jest ignorowane.
Błąd nr 3: Używanie Map jak zwykłej kolekcji. Map to nie lista ani zbiór. Do iteracji używaj keySet(), values() lub entrySet().
Błąd nr 4: Oczekiwanie zachowania kolejności w HashSet lub HashMap. HashSet i HashMap nie gwarantują kolejności. Jeśli jest ważna — użyj LinkedHashSet albo LinkedHashMap.
Błąd nr 5: Używanie List do unikalnych elementów. Jeśli potrzebna jest unikalność — użyj Set. List nie zapobiega duplikatom.
GO TO FULL VERSION