1. Che cos’è l’interfaccia Collection
In Java un’interfaccia è come un contratto: se una classe implementa un’interfaccia, è tenuta a fornire l’implementazione di tutti i suoi metodi. L’interfaccia di per sé non mantiene stato e non contiene codice (quasi: a partire da Java 8 sono possibili i metodi default, ma qui conta l’idea di base).
Collection è l’interfaccia di base per la maggior parte delle collezioni in Java. Definisce che cosa una collezione sa fare: aggiungere elementi, rimuoverli, ottenere la dimensione, verificare la presenza di elementi ecc.
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();
// ... e ancora un sacco di metodi utili
}
Metodi chiave:
- add(E e) — aggiungere un elemento.
- remove(Object o) — rimuovere un elemento.
- size() — ottenere il numero di elementi.
- isEmpty() — verificare se la collezione è vuota.
- contains(Object o) — verificare la presenza di un elemento.
- clear() — svuotare la collezione.
- iterator() — ottenere un iteratore per l’iterazione.
Perché Map non estende Collection?
Map sta a sé tra le collezioni. Perché Map è un insieme di coppie «chiave → valore», non un semplice insieme di elementi. Ha un contratto diverso e un altro set di metodi. Ad esempio, in Map non esiste il metodo add, perché l’inserimento si fa tramite put(key, value), e non ha senso verificare la presenza di un valore senza conoscere la chiave.
2. Gerarchia delle collezioni
L’«albero» mentale delle principali interfacce è così:
Iterable
|
Collection
/ | \
List Set Queue
|
Deque
- Iterable — l’interfaccia più basilare: tutto ciò che può essere iterato in un ciclo for-each.
- Collection — estende Iterable, aggiunge operazioni per lavorare con una collezione di elementi.
- Tre rami principali:
- List — lista ordinata, consente duplicati.
- Set — insieme di elementi unici, l’ordine dipende dall’implementazione.
- Queue — coda (di solito FIFO); sottotipo — Deque (coda a doppia estremità).
E Map vive a parte:
Map
/ \
HashMap TreeMap
Visualizzazione della gerarchia (schema)
+--------------------+
| Iterable<E> |
+--------------------+
|
+--------------------+
| Collection<E> |
+--------------------+
/ | \
+--------+ +-------+ +-------+
| List | | Set | | Queue |
+--------+ +-------+ +-------+
|
+------+
|Deque |
+------+
+--------------------+
| Map<K,V> |
+--------------------+
3. List: collezione ordinata con duplicati
List è una collezione in cui:
- L’ordine degli elementi è importante (primo, secondo, terzo…).
- Sono ammessi elementi uguali (duplicati).
- Si può ottenere un elemento per indice (list.get(2)), sostituirlo, inserirlo in qualsiasi posizione.
Esempi di implementazioni: ArrayList — accesso veloce per indice; LinkedList — buono con inserimenti/rimozioni frequenti in mezzo.
import java.util.*;
List<String> shoppingList = new ArrayList<>();
shoppingList.add("Latte");
shoppingList.add("Pane");
shoppingList.add("Formaggio");
shoppingList.add("Pane"); // I duplicati sono consentiti!
System.out.println(shoppingList.get(1)); // "Pane"
Metodi tipici di 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: insieme di elementi unici
Set è una collezione in cui:
- Ogni elemento è unico (niente duplicati).
- L’ordine di memorizzazione non è garantito in HashSet, può esserci ordinamento in TreeSet o ordine di inserimento in LinkedHashSet.
Esempi di implementazioni: HashSet, TreeSet, LinkedHashSet.
import java.util.*;
Set<String> uniqueNames = new HashSet<>();
uniqueNames.add("Anya");
uniqueNames.add("Boris");
uniqueNames.add("Anya"); // Non verrà aggiunto — è già presente!
System.out.println(uniqueNames.contains("Anya")); // true
System.out.println(uniqueNames.size()); // 2
Metodi tipici di Set:
- add(E e), remove(Object o)
- contains(Object o)
- size(), isEmpty()
5. Map: collezione di coppie chiave-valore
Map è una collezione in cui:
- Ogni elemento è una coppia chiave → valore.
- Le chiavi sono uniche, i valori possono ripetersi.
- Accesso rapido per chiave.
Esempi di implementazioni: HashMap, TreeMap, LinkedHashMap.
import java.util.*;
Map<String, String> phoneBook = new HashMap<>();
phoneBook.put("Anya", "+19991112233");
phoneBook.put("Boris", "+19994445566");
phoneBook.put("Anya", "+19990001122"); // Sovrascriverà il numero di Anya!
System.out.println(phoneBook.get("Anya")); // "+19990001122"
System.out.println(phoneBook.containsKey("Boris")); // true
Metodi tipici di Map:
- put(K key, V value), get(K key)
- remove(K key)
- containsKey(K key), containsValue(V value)
- keySet(), values(), entrySet()
6. Visualizzazione della gerarchia: tutto in un’unica immagine
Una piccola tabella riassuntiva:
| Interfaccia | Descrizione | Esempi di implementazioni | Caratteristiche chiave |
|---|---|---|---|
|
Elenco ordinato | |
Accesso per indice, duplicati |
|
Insieme di valori unici | |
Solo elementi unici |
|
Coppie chiave-valore | |
Chiavi uniche, valori qualsiasi |
Gerarchia nello schema:
Collection
/ | \
List Set Queue
|
Deque
Map (separata)
7. Quando usare quale interfaccia
List
- Quando è importante l’ordine degli elementi (per esempio, lo storico delle azioni dell’utente).
- Quando servono duplicati (per esempio, righe d’ordine).
- Quando serve accesso/sostituzione rapida per indice.
Set
- Quando serve unicità (email, login, id).
- Quando l’ordine non è importante, oppure — al contrario — serve un insieme ordinato automaticamente (TreeSet).
Map
- Quando devi associare chiavi e valori (id → oggetto, login → profilo).
- Quando serve una ricerca veloce per chiave.
- Quando le chiavi devono essere uniche e i valori — no.
8. Errori tipici nel lavorare con la gerarchia delle collezioni
Errore n. 1: usare l’interfaccia sbagliata nella dichiarazione della variabile. Se scrivi ArrayList<String> list = new ArrayList<>();, ti leghi rigidamente all’implementazione. È preferibile List<String> list = new ArrayList<>(); — così è più facile sostituire l’implementazione.
Errore n. 2: provare ad aggiungere duplicati in Set e aspettarsi che compaiano. Non è un bug, è una caratteristica: Set per definizione non memorizza duplicati. L’inserimento ripetuto viene ignorato.
Errore n. 3: usare Map come una collezione normale. Map non è né una lista né un insieme. Per l’iterazione usa keySet(), values() o entrySet().
Errore n. 4: aspettarsi un ordine in HashSet o HashMap. HashSet e HashMap non garantiscono l’ordine. Se è importante — usa LinkedHashSet o LinkedHashMap.
Errore n. 5: usare List per elementi unici. Se serve unicità — usa Set. List non previene i duplicati.
GO TO FULL VERSION