W3docs

Interfaccia Collection in Java

L'interfaccia radice Collection in Java e il contratto ereditato da ogni lista, set e coda.

java.util.Collection<E> è la radice della parte del framework che contiene elementi singoli — ogni List, Set, Queue e Deque la implementa (l'unica famiglia che non lo fa è Map, i cui elementi sono entry, non valori singoli). Tutto ciò che puoi fare "indipendentemente dal gruppo" — aggiungere, rimuovere, verificare con contains, iterare, contare, convertire in array, usare stream — è dichiarato qui. Questo capitolo descrive il contratto: i metodi su cui puoi fare affidamento per qualsiasi collection, i pochi che possono lanciare eccezioni, e il modello di iterazione che ogni implementazione eredita.

La gerarchia in sintesi

Iterable<E>
  └── Collection<E>
        ├── List<E>           — ordered, indexed, duplicates allowed
        ├── Set<E>            — no duplicates
        │     └── SortedSet<E> → NavigableSet<E>
        └── Queue<E>          — "next in line"
              └── Deque<E>    — double-ended queue

Collection estende Iterable<E>, motivo per cui ogni collection funziona con il ciclo for-each. Le due specializzazioni di CollectionSet e Queue — affinano il contratto; Map ha una propria radice.

Metodi principali presenti in ogni collection

Di seguito è riportato l'insieme completo dei metodi di istanza su Collection, raggruppati per scopo. Memorizza le categorie piuttosto che la lista — una volta che sai che esiste un metodo chiamato removeIf puoi trovarlo facilmente.

Dimensione e vuoto

  • int size() — conteggio degli elementi.
  • boolean isEmpty() — equivalente a size() == 0 ma spesso più veloce.

Aggiunta

  • boolean add(E e) — aggiunge un elemento. Restituisce true se la collection è cambiata. (Un Set restituisce false per un duplicato.)
  • boolean addAll(Collection<? extends E> c) — aggiunge ogni elemento di c.

Rimozione

  • boolean remove(Object o) — rimuove una occorrenza di o.
  • boolean removeAll(Collection<?> c) — rimuove ogni elemento che compare in c.
  • boolean retainAll(Collection<?> c) — mantiene solo gli elementi in c (intersezione).
  • boolean removeIf(Predicate<? super E> filter) — rimuove ogni elemento che soddisfa il predicato. Il modo più pulito per filtrare in place.
  • void clear() — svuota la collection.

Interrogazione

  • boolean contains(Object o) — verifica l'appartenenza.
  • boolean containsAll(Collection<?> c) — verifica il sottoinsieme.

Iterazione e viste bulk

  • Iterator<E> iterator() — l'iteratore sottostante; quello usato dal for-each.
  • Stream<E> stream() / parallelStream() — apre un Stream sugli elementi.
  • void forEach(Consumer<? super E> action) — ereditato da Iterable. La forma di iterazione funzionale.

Conversione in array

  • Object[] toArray()
  • <T> T[] toArray(T[] a) e il più recente <T> T[] toArray(IntFunction<T[]> generator) (Java 11+) — array tipizzato.

Questa è l'intera interfaccia. Ogni lista, set e coda che incontrerai in questa parte è solo un'implementazione diversa di questi metodi più alcuni propri.

Uguaglianza ed equals / hashCode

Collection.equals(Object) non è definito sulla radice — ogni sotto-interfaccia specifica cosa significa uguaglianza per essa. List richiede stessi elementi nello stesso ordine; Set richiede stessi elementi indipendentemente dall'ordine; Queue non definisce equals (una LinkedList come coda e una ArrayDeque con lo stesso contenuto non sono uguali perché il confronto ricade sull'identità). Non confrontare collection tra famiglie diverse aspettandosi simmetria.

Gli elementi memorizzati in una Collection devono avere un equals / hashCode sensato se vuoi che contains, remove e (per le collection basate su hash) le ricerche funzionino correttamente. Abbiamo trattato il contratto nel capitolo equals e hashCode — questo è il prerequisito per usare Set e Map con le proprie classi.

Operazioni opzionali

Alcune collection sono non modificabili — List.of(1,2,3), Collections.unmodifiableList(list), le viste restituite da Map.keySet() su certe implementazioni, ecc. Implementano comunque Collection, ma chiamare add, remove, clear, o qualsiasi metodo mutante lancia UnsupportedOperationException. La Javadoc le chiama "operazioni opzionali." È il modo più vicino che Java ha a un opt-out a runtime per parti di un'interfaccia; il prezzo è che il compilatore non può rilevare l'errore — lo scopri al primo lancio.

Una regola sicura: se non hai costruito tu la collection, trattala come potenzialmente non modificabile. Se hai bisogno di una copia mutabile, fai prima new ArrayList<>(received).

Iterazione: tre forme, un meccanismo sottostante

Ogni collection supporta tre stili di iterazione, e tutti e tre finiscono per chiamare iterator():

Collection<String> names = List.of("Ada", "Linus", "Grace");

// 1. for-each — the everyday form
for (String n : names) System.out.println(n);

// 2. forEach with a lambda — declarative
names.forEach(System.out::println);

// 3. Iterator — when you need to remove during iteration
Iterator<String> it = names.iterator();
while (it.hasNext()) {
  String s = it.next();
  if (s.startsWith("L")) it.remove();   // safe; for-each can't do this
}

Perché le forme 1 e 3 contano ancora entrambe: il ciclo for-each non può modificare la collection sottostante senza lanciare ConcurrentModificationException. Quando devi rimuovere durante l'iterazione, usi l'Iterator esplicito. Il capitolo sugli Iteratori più avanti in questa parte copre il protocollo in dettaglio.

Algebra degli insiemi con le operazioni bulk

Le operazioni bulk trasformano una collection in un calcolatore di algebra degli insiemi (indipendentemente dal fatto che sia un Set — funzionano anche su List):

Collection<Integer> a = new ArrayList<>(List.of(1, 2, 3, 4));
Collection<Integer> b = List.of(3, 4, 5);

a.addAll(b);                 // union (multiset)
a.retainAll(List.of(3, 4));  // intersection
a.removeAll(List.of(3));     // difference

Questi sono il modo sicuro e senza dipendenze per esprimere "mantieni solo gli elementi presenti anche in b" senza scrivere un ciclo. Modificano il ricevitore — se hai bisogno di un risultato immutabile, copia prima.

Un esempio pratico: tutti i metodi, uno accanto all'altro

Il programma seguente esercita ogni categoria di metodo di Collection sullo stesso ArrayList, così puoi vederli in un unico posto e osservare il contratto in azione.

java— editable, runs on the server

Due cose degne di nota dall'output:

  1. remove("red") ha rimosso solo la prima occorrenza — questo è il contratto su Collection. Per rimuovere ogni corrispondenza, usa removeIf (lo hai visto subito dopo, rimuovendo ogni parola più lunga di quattro caratteri).
  2. L'UnsupportedOperationException da frozen.add("d") è la regola delle "operazioni opzionali" in azione. frozen implementa Collection, quindi la chiamata compila. L'implementazione ha scelto di non supportarla, e lo scopri a runtime.

Cosa viene dopo

Collection è il contratto astratto. Il primo perfezionamento concreto che incontrerai è quello che aggiunge ordine e indicizzazione — l'interfaccia List. Lì entrano in scena l'accesso indicizzato, i sotto-elenchi e le operazioni che preservano l'ordine.

Esercitazione

Pratica
Hai una `Collection<String>` e vuoi rimuovere ogni elemento la cui lunghezza è maggiore di quattro. Qual è l'approccio idiomatico in una singola istruzione?
Hai una `Collection<String>` e vuoi rimuovere ogni elemento la cui lunghezza è maggiore di quattro. Qual è l'approccio idiomatico in una singola istruzione?
Was this page helpful?