![]() ![]() |
|
Le classi java.util.Vector e java.util.ArrayList definiscono degli oggetti, chiamati vettori, che consentono di rappresentare sequenze di oggetti di lunghezza variabile. Ciascun oggetto in un vettore ha un numero intero, detto indice, che ne indica la posizione nel vettore. Grazie all'indice è possibile accedere indipendentemente a ciascun elemento della sequenza. L'accesso ad una posizione inesistente provoca un errore (viene lanciata un'eccezione). Al momento della dichiarazione o creazione di un vettore, il tipo base degli elementi del vettore va indicato tra parentesi angolate dopo il nome della classe (Vector e ArrayList sono classi generiche, un concetto che approfondiremo tra breve). Ad esempio, per costruire un vettore di stringhe (inizialmente vuoto) e assegnarlo alla variabile vet, scriveremo:
I vettori sono dunque simili agli array. Le differenze principali sono due:
Successivamente, se la capacità dell'array non è più sufficiente, viene creato un nuovo array più grande nel quale vengono copiati tutti gli elementi del vecchio.
|
![]() ![]() |
|
![]() ![]() |
Nel seguito, usando la sintassi Java 6.0, indicheremo con Vector<E> e ArrayList<E> le classi generiche che definiscono i vettori quando il tipo base non è specificato.
Si noti che <E> può essere considerata una variabile di tipo, che può essere istanziata con qualunque classe Java.
Le classi generiche Vector<E> e ArrayList<E> sonosostanzialmente equivalenti, ma:
|
![]() ![]() |
|
![]() ![]() |
I costruttori di Vector<E>
permettono di specificare la capacità iniziale del vettore (initialCapacity)
e il valore da usare per aumentare la capacità
(capacityIncrement) quando
necessario. Se (capacityIncrement == 0), il nuovo array
avrà capacità doppia rispetto all'attuale.
I costruttori di ArrayList<E> permettono di specificare solo la capacità iniziale del vettore.
|
![]() ![]() |
|
![]() ![]() |
I metodi che operano sui vettori consentono tra l'altro di:
|
![]() ![]() |
|
![]() ![]() |
Sottolineiamo alcune differenze sintattiche nell'uso di un vettore al
posto di un array. Si noti che il for generalizzato può essere usato anche per scandire gli elementi di un vettore: la sintassi è identica a quella vista per scandire un array.
|
![]() ![]() |
|
![]() ![]() |
Come anticipato, il tipo base di un vettore
non può essere un tipo primitivo: quindi è illegale
ad esempio dichiarare una variabile di tipo ArrayList<int> oppure Vector<double>.
Java fornisce tuttavia le cosiddette classi involucro o classi contenitore, che possono essere usate come tipo base di vettori in cui si vogliano memorizzare numeri interi, numeri in virgola mobile, o valori booleani. Le istanze di una classe involucro sono usate per incapsulare valori primitivi all'interno di un oggetto. Questo permette di trattare in maniera omogenea dati di tipi primitivi ed oggetti. La conversione tra un tipo di dati primitivo e la corrispondente classe involucro è automatica, grazie al meccanismo di autoboxing/unboxing introdotto in Java 5.0. Ci sono classi involucro per tutti i tipi primitivi. Normalmente hanno un nome simile al corrispondente tipo primitivo, ma iniziano con maiuscola:
|
![]() ![]() |
|
![]() ![]() |
La classe Integer
è la classe involucro per numeri interi. Grazie all'autoboxing/unboxing
è possibile assegnare valori di tipo int a variabili di tipo Integer
e viceversa.
Nel primo comando viene invocato implicitamente un costruttore che crea un oggetto di tipo Integer a partire da un valore di tipo int. Nel secondo caso viene invocato implicitamente sull'oggetto di tipo Integer il metodo intValue(). Quindi i due comandi visti sono equivalenti ai seguenti:
La classe Integer fornisce diversi altri membri. Tra questi ricordiamo le costanti Integer.MAX_VALUE (2147483647) e Integer.MIN_VALUE (-2147483648), che sono il più grande e il più piccolo valore rappresentabile in una variabile di tipo int, e il metodo statico parseInt(), che permette di convertire una stringa in un intero:
Un metodo analogo è il metodo parseDouble() della classe Double, che converte una stringa nel numero in virgola mobile che rappresenta. Come vedremo, questi metodi lanciano un'eccezione se la stringa su cui sono invocati non rappresenta un numero.
Vediamo ora un semplice esempio di manipolazione di un vettore di interi. Si osservi che il tipo base del vettore è Integer.
Si osservi che, grazie alla conversione automatica tra Integer e int, il codice è simile a quello che avremmo scritto usando un array di int al posto del vettore. A livello di esecuzione del codice, tuttavia, le differenze sono notevoli. Infatti mentre un assegnamento come arr[i] = n comporta semplicemente la copia del valore della variabile n nella variabile arr[i], l'esecuzione del comando vet.add(n) causa la creazione di un nuovo oggetto di tipo Integer e l'invocazione del metodo add. |
![]() ![]() |
|
![]() ![]() |
L'interfaccia Iterable<T>
deve essere implementata dalle collezioni che possono essere scandite con il for semplificato.
Queste non sono ovviamente ristrette alle classi delle Api di Java ma possiamo farci le nostre
|
![]() ![]() |
|
![]() ![]() |
|