Java Collections Framework

Java Collections Framework

In questo articolo vedremo un insieme di Interfacce e Classi Java, denominato Java Collections Framework (JCF), che si occupano di definire ed impleme

Integrare Apache Tomcat in Eclipse
Installare Alfresco su JBoss
Sviluppare con il Google Web Toolkit (GWT)

In questo articolo vedremo un insieme di Interfacce e Classi Java, denominato Java Collections Framework (JCF), che si occupano di definire ed implementare le Collection, che possiamo assimilare a dei contenitori, in cui più oggetti vengono raggruppati in una singola unità (a sua volta un oggetto). Le Collection sono strutture dati usate per conservare, reperire, manipolare e comunicare dati aggregati.

Il Java Collections Framework è stato introdotto a partire dalla JDK 1.2 ed è in continua evoluzione (ad esempio con la JDK 1.5 sono stati introdotte le versioni concorrenti (synchronized) delle Classi che compongono il JCF).

Il Java Collections Framework è un’architettura unificata per poter manipolare collezioni di oggetti e contiene i seguenti elementi:

  • Interfacce: tipi di dato astratto che rappresentano le collezioni. Le interfacce permettono di manipolare i dati senza entrare nei dettagli della singola implementazione, così come è possibile fare con una qualsiasi interfaccia presente nel mondo Java;
  • Implementazioni: essenzialmente delle Classi che implementano le interfacce suddette;
  • Algoritmi: sono metodi utilizzati per compiere operazioni sulle Collezioni, quali ad esempio operazioni di sorting (ordinamento) e di ricerca. Gli algoritmi sono polimorfici in quanto lo stesso metodo può essere applicato su implementazioni diverse a seconda della particolare Collection.

Prima dell’avvento di questo framework c’erano solo tre metodi per raggruppare oggetti in Java:

  • una oggetto Array;
  • la classe Vector;
  • la classe Hashtable.

L’array non è una classe contenuta nella JCF, ma piuttosto una struttura N-dimensionale che contiene N variabili (o oggetti) dello stesso tipo,  individualmente accessibili tramite un indice numerico. Essendo un oggetto viene inizializzato con la keyword new ed ha dimensione fissa .

Un array di 10 elementi

Da notare che il primo elemento di un array ha indice uguale a 0.

Ad esempio il seguente codice:

int[] vettore = new int[45];

definisce un array di 45 elementi di tipo int. E’ possibile anche utilizzare una notazione alternativa che prevede l’utilizzo delle parentesi quadre dopo il nome dell’array:

int vettore[] = new int [45];

L’utilizzo di questa notazione è tuttavia scoraggiato, in quanto le parentesi quadre identificano il tipo come array e quindi vanno poste nella dichiarazione del tipo.

Vediamo ora un piccolo programma che inizializza un array ed accede ai suoi elementi:

class ArrayDemo {
public static void main(String[] args) {
// dichiara un array di interi
int[] array;
// alloca spazio in memoria per 10 interi
array = new int[10];
// inizializza il primo elemento con il valore 100
array[0] = 100;
// inizializza il secondo elemento con il valore 200
array[1] = 200;
// etc.
array[2] = 300;
array[3] = 400;
array[4] = 500;
array[5] = 600;
array[6] = 700;
array[7] = 800;
array[8] = 900;
array[9] = 1000;
//stampa i valori
System.out.println("Elemento con indice 0: "+ array[0]);
System.out.println("Elemento con indice 1: "+ array[1]);
System.out.println("Elemento con indice 2: "+ array[2]);
System.out.println("Elemento con indice 3: "+ array[3]);
System.out.println("Elemento con indice 4: "+ array[4]);
System.out.println("Elemento con indice 5: "+ array[5]);
System.out.println("Elemento con indice 6: "+ array[6]);
System.out.println("Elemento con indice 7: "+ array[7]);
System.out.println("Elemento con indice 8: "+ array[8]);
System.out.println("Elemento con indice 9: "+ array[9]);
}
}

E’ possibile anche inizializzare un array all’atto della creazione:

int[] array = {
100, 200, 300,
400, 500, 600,
700, 800, 900, 1000
};

Infine è possibile definire degli array multidimensionali:

String[][] nomi= {
{"Mr. ", "Mrs. ", "Ms. "},
{"Smith", "Jones"}
};

L’oggetto array espone un’unica proprietà di nome lenght, tramite la quale è possibile conoscere il numero di elementi contenuti in un array:

System.out.println(array.length);

Esiste poi la classe di utilità System che espone il metodo statico arraycopy, che permette di copiare gli elementi di un array in un altro, specificando anche da quale posizione partire e quanti elementi copiare:

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

Vediamo un piccolo programma di esempio:

class ArrayCopyDemo {
public static void main(String[] args) {
char[] copiaDa = { 'a', 'p', 'p', 'u', 'n', 't', 'i', 's', 'o', 'f', 't', 'w', 'a', 'r', 'e' };
char[] copiaA = new char[8];
System.arraycopy(copiaDa, 8, copiaA, 0, 7);
System.out.println(new String(copiaA));
}
}

Il metodo println stampa la stringa “software”.

Una Hashtable o un Vector sono invece le prime Collection Classes ad essere state implementate, entrambe possono contenere gruppi di oggetti, ma differiscono nel modo in cui li conservano. Una Hashtable è un dizionari, essa conserva e permette di recuperare un oggetto attraverso una chiave univoca, proprio come si fa quando si vuole cercare una parola in un dizionario. Un Vector invece contiene una serie di oggetti in modo ordinato, i quali sono accessibili tramite un indice come abbiamo visto per gli array, ma a differenza di essi, la dimensione può variare nel tempo (può crescere e/o diminuire dinamicamente).

La prima cosa da notare è che entrambe le due Classi sono state conformate al JCF, infatti Vector implementa l’Interfaccia List, mentre Hashtable implementa l’interfaccia Map, di conseguenza avremo nelle classi dei metodi che implementano essenzialmente le stesse funzionalità proprio perchè è stato necessario fornire metodi che implementassero le nuove interfacce.

Ricordiamo inoltre che entrambe le classi sono thread-safe, cioè l’accesso contemporaneo all’insieme da parte di più thread è mutuamente esclusivo, è come se i suoi metodi fossero implicitamente circondati da un blocco synchronized.

Infatti la classe Vector fornisce sia il metodo get(int index) che il metodo elementAt(int index) che entrambe ritornano l’elemento con indice index, ma appunto il metodo get è stato implementato per potersi conformare alla interfaccia List.

Vediamo ora come utilizzare a classe Vector:

Vector insieme= new Vector();
String uno = "uno";
String due = "due";
String tre = "tre";
insieme.addElement( uno);
insieme.addElement( tre);
insieme.insertElementAt( due, 1 );

Costruiamo così un insieme ordinato di  tre stringhe, e se stampassimo a video il contenuto in modo sequenziale, otteniamo la serie “uno”, “due”, “tre” perchè il metodo insertElementAt ci permette di inserire un elemento in una posizione e di scalare i successivi.

Altri metodi utili sono:

String s1 = (String)insieme.firstElement(); // otteniamo "uno"
String s3 = (String)insieme.lastElement(); // otteniamo "tre"
String s2 = (String)insieme.elementAt(1); // otteniamo "due"
int i = insieme.indexOf( tre ); // otteniamo i = 2
boolean trovato = insieme.removeElement( due); //rimuove l'elemento due

I primi 3 metodi servono per recuperare un oggetto dalla collezione, il quarto cerca nell’insieme la prima occorrenza di un oggetto e ritorna l’indice più piccolo o -1 se non è stato trovato (per effettuare la comparazione tra oggetti si usa il metodo equals dell’oggetto passato). Il quinto metodo  infine rimuove dalla collezione l’oggetto passato (quello con indice più basso se ce ne sono  molteplici) e ritorna true se è stato trovato nell’insieme.

La classe Hashtable invece memorizza oggetti al suo interno associandoli ad una chiave, che può essere o un tipo primitivo o un oggetto. Se la chiave è un oggetto essa deve implementare il metodo hashCode che ritorna un numero intero possibilmente univoco, e d il metodo equals.

Vediamo un piccolo esempio di Hashtable:

Hashtable numeri = new Hashtable();
numeri.put("uno", new Integer(1));
numeri.put("due", new Integer(2));
numeri.put("tre", new Integer(3));

per ottenere un oggetto dato una chiave, utilizziamo il metodo get(object key):

Integer n = (Integer)numeri.get("due");
if (n != null) {
System.out.println("due= " + n);
}
Older Post

COMMENTS

WORDPRESS: 1
  • comment-avatar

    Guida interessante e completa