ATTENZIONE: il nuovo sito di riferimento per questa guida e altre cose più
o meno interessanti è
il mio BLOG
Molto spesso si ha necessità di conservare degli oggetti in una struttura dati. La scelta migliore per semplicità e velocità è l'array, ma non sempre è applicabile.
La libreria java.util fornisce delle collezioni pronte all'uso, strutturate in una gerarchia che prevede tre interfacce principali - List, Set e Map - e varie implementazioni.
Un Set (insieme) è un contenitore che mantiene una sola copia dell'oggetto, mentre Map è un'associazione (funzione) chiave - valore.
Ecco un esempio di lista:
List capitali = new ArrayList(); capitali.add("Roma"); capitali.add("Parigi"); 5 capitali.add("Londra"); System.out.println(capitali);È opportuno usare le interfacce invece delle implementazioni (linea 1).
In linea 7 viene chiamato il metodo toString()
, che fornisce una
rappresentazione del contenuto della lista.
Se si prova a fare lo stesso con un array si vede che toString()
non fornisce la stessa informazione; in questo caso si possono usare i metodi
statici toString(...)
o deepToString(...)
della classe Arrays.
Una collezione contiene Object, quindi quando si recuperano gli oggetti è necessario il casting - continuando l'esempio precedente:
String it = (String) capitali.get(0);Java 1.5 ha introdotto generics e autoboxing, che permettono un uso più diretto e sicuro delle collezioni:
List<String> capitali = new ArrayList<String>();In questo modo
capitali
non è più una lista di oggetti,
ma di stringhe, quindi il casting non serve.
L'autoboxing (e specularmente unboxing) invece consente di creare liste di tipi primitivi:
List<Integer> primi = new ArrayList<Integer>(); primi.add(2); // autoboxinge più in generale di usare un tipo primitivo quando viene richiesto un tipo wrapper (Integer, Float, ecc.) o Object o Number (superclassi).
Il modo standard di accedere agli elementi di una collezione è tramite un Iterator:
Iterator i = capitali.iterator(); while(i.hasNext()) System.out.println(i.next());In java 5 una collezione si può visitare molto più agevolmente con l'enhanced for, già visto in azione per gli array:
for(String c : capitali) System.out.println(c);
In conclusione di questo capitolo vediamo un semplice esempio di implementazione di pila generica - nel main() un esempio d'uso:
import java.util.*; /** Pila generica. * Usa la nuova (1.5) interfaccia Queue, implementata da LinkedList. */ public class Pila<T> // notare il "segnaposto" per il tipo { private LinkedList<T> pila; /** Crea una pila vuota */ public Pila() { pila = new LinkedList<T>(); } /** Mette un elemento in testa alla pila. * @param el l'elemento da inserire. */ public void push(T el) { pila.addFirst(el); } /** Estrae un elemento dalla pila. * @return L'elemento estratto. * @throws NoSuchElementException se la pila e' vuota. */ public T pop() { return pila.remove(); // Queue, Java 1.5+ } public String toString() { return pila.toString(); } /** MAIN - per test */ public static void main(String... args) { // crea una pila vuota di Integer Pila<Integer> p = new Pila<Integer>(); /* mette sulla pila 23, 0, -22 usa autoboxing, java 1.5 o superiore */ p.push(23); p.push(0); p.push(-22); System.out.println(p); System.out.println(p.pop()); System.out.println(p); p.pop(); p.pop(); // ora la pila e' vuota! System.out.println(p); p.pop(); // lancia NoSuchElementException } }