Interfaccia Collection in Java

Concetti Chiave
  • L'interfaccia Collection è la base del Collections Framework in Java.
  • Definisce metodi fondamentali per la gestione delle collezioni di oggetti.
  • È implementata da tutte le classi che rappresentano collezioni.
  • I metodi principali includono add(), remove(), contains(), size(), e iterator().

L'Interfaccia Collection

L'interfaccia Collection è la base su cui è costruito il Collections Framework perché deve essere implementata da qualsiasi classe che definisce una collezione.

Collection è un'interfaccia generica che ha questa dichiarazione:

interface Collection<E>

Qui, E specifica il tipo di oggetti che la collezione conterrà. Collection estende l'interfaccia Iterable. Questo significa che tutte le collezioni possono essere attraversate utilizzando il ciclo for in stile foreach. (Ricordiamo che solo le classi che implementano Iterable possono essere attraversate dal for).

Collection dichiara i metodi fondamentali che tutte le collezioni avranno. Questi metodi sono riassunti nella Tabella seguente:

Metodo Descrizione
boolean add(E ogg) Aggiunge ogg alla collezione invocante. Restituisce true se ogg è stato aggiunto alla collezione. Restituisce false se ogg è già un membro della collezione e la collezione non consente duplicati.
boolean addAll(Collection<? extends E> c) Aggiunge tutti gli elementi di c alla collezione invocante. Restituisce true se la collezione è cambiata (cioè, gli elementi sono stati aggiunti). Altrimenti, restituisce false.
void clear() Rimuove tutti gli elementi dalla collezione invocante.
boolean contains(Object ogg) Restituisce true se ogg è un elemento della collezione invocante. Altrimenti, restituisce false.
boolean containsAll(Collection<?> c) Restituisce true se la collezione invocante contiene tutti gli elementi di c. Altrimenti, restituisce false.
boolean equals(Object ogg) Restituisce true se la collezione invocante e ogg sono uguali. Altrimenti, restituisce false.
int hashCode() Restituisce il codice hash per la collezione invocante.
boolean isEmpty() Restituisce true se la collezione invocante è vuota. Altrimenti, restituisce false.
Iterator<E> iterator() Restituisce un iteratore per la collezione invocante.
default Stream<E> parallelStream() Restituisce uno stream che usa la collezione invocante come sua sorgente per gli elementi. Se possibile, lo stream supporta operazioni parallele.
boolean remove(Object ogg) Rimuove un'istanza di ogg dalla collezione invocante. Restituisce true se l'elemento è stato rimosso. Altrimenti, restituisce false.
boolean removeAll(Collection<?> c) Rimuove tutti gli elementi di c dalla collezione invocante. Restituisce true se la collezione è cambiata (cioè, gli elementi sono stati rimossi). Altrimenti, restituisce false.
default boolean removeIf(Predicate<? super E> predicato) Rimuove dalla collezione invocante quegli elementi che soddisfano la condizione specificata dal predicato.
boolean retainAll(Collection<?> c) Rimuove tutti gli elementi dalla collezione invocante eccetto quelli in c. Restituisce true se la collezione è cambiata (cioè, gli elementi sono stati rimossi). Altrimenti, restituisce false.
int size() Restituisce il numero di elementi contenuti nella collezione invocante.
default Spliterator<E> spliterator() Restituisce uno spliterator alle collezioni invocanti.
default Stream<E> stream() Restituisce uno stream che usa la collezione invocante come sua sorgente per gli elementi. Lo stream è sequenziale.
default <T> T[] toArray(IntFunction<T[]> generatoreArray) Restituisce un array degli elementi dalla collezione invocante. L'array restituito è creato dalla funzione specificata da generatoreArray. Una ArrayStoreException viene lanciata se qualsiasi elemento della collezione ha un tipo che non è compatibile con il tipo dell'array.
Object[] toArray() Restituisce un array degli elementi dalla collezione invocante.
default <T> T[] toArray(T[] array) Restituisce un array degli elementi dalla collezione invocante. Se la dimensione di array è uguale al numero di elementi, questi vengono restituiti in array. Se la dimensione di array è minore del numero di elementi, un nuovo array della dimensione necessaria viene allocato e restituito. Se la dimensione di array è maggiore del numero di elementi, l'elemento dell'array che segue l'ultimo elemento della collezione viene impostato a null. Una ArrayStoreException viene lanciata se qualsiasi elemento della collezione ha un tipo che non è compatibile con il tipo dell'array.
Tabella 1: I Metodi Dichiarati da Collection

Poiché tutte le collezioni implementano Collection, la familiarità con i suoi metodi è necessaria per una comprensione chiara del framework. Diversi di questi metodi possono lanciare un'UnsupportedOperationException. Come spiegato, questo si verifica se una collezione non può essere modificata. Una ClassCastException viene generata quando un oggetto è incompatibile con un altro, come quando si tenta di aggiungere un oggetto incompatibile a una collezione. Una NullPointerException viene lanciata se si tenta di memorizzare un oggetto null e gli elementi null non sono consentiti nella collezione. Una IllegalArgumentException viene lanciata se viene utilizzato un argomento non valido. Una IllegalStateException viene lanciata se si tenta di aggiungere un elemento a una collezione di lunghezza fissa che è piena.

Gli oggetti vengono aggiunti a una collezione chiamando add(). Notare che add() prende un argomento di tipo E, il che significa che gli oggetti aggiunti a una collezione devono essere compatibili con il tipo di dati atteso dalla collezione. È possibile aggiungere l'intero contenuto di una collezione a un'altra chiamando addAll().

È possibile rimuovere un oggetto utilizzando remove(). Per rimuovere un gruppo di oggetti, chiamare removeAll(). È possibile rimuovere tutti gli elementi eccetto quelli di un gruppo specificato chiamando retainAll(). Per rimuovere un elemento solo se soddisfa una certa condizione, è possibile utilizzare removeIf(). Per svuotare una collezione, chiamare clear().

È possibile determinare se una collezione contiene un oggetto specifico chiamando contains(). Per determinare se una collezione contiene tutti i membri di un'altra, chiamare containsAll(). È possibile determinare quando una collezione è vuota chiamando isEmpty(). Il numero di elementi attualmente contenuti in una collezione può essere determinato chiamando size().

I metodi toArray() restituiscono un array che contiene gli elementi memorizzati nella collezione. Il primo restituisce un array di Object. Il secondo restituisce un array di elementi che hanno lo stesso tipo dell'array specificato come parametro. Normalmente, la seconda forma è più conveniente perché restituisce il tipo di array desiderato. A partire da JDK 11, è stata aggiunta una terza forma che permette di specificare una funzione che ottiene l'array. Questi metodi sono più importanti di quanto possa sembrare inizialmente. Spesso, elaborare il contenuto di una collezione utilizzando una sintassi simile agli array è vantaggioso. Fornendo un percorso tra collezioni e array, è possibile avere il meglio di entrambi i mondi.

Due collezioni possono essere confrontate per uguaglianza chiamando equals(). Il significato preciso di "uguaglianza" può differire da collezione a collezione. Ad esempio, è possibile implementare equals() in modo che confronti i valori degli elementi memorizzati nella collezione. In alternativa, equals() può confrontare i riferimenti a quegli elementi.

Un altro metodo importante è iterator(), che restituisce un iteratore a una collezione. Il metodo spliterator() restituisce uno spliterator alla collezione. Gli iteratori sono frequentemente utilizzati quando si lavora con le collezioni. Infine, i metodi stream() e parallelStream() restituiscono uno Stream che utilizza la collezione come sorgente di elementi. Nelle prossime lezioni vedremo in dettaglio l'interfaccia Stream e come utilizzarla per elaborare i dati in modo efficiente.