Java Java Collections Framework Pag. 1/19 Array L'array è l'unica collezione supportata internamente dal linguaggio Java, deriva da Object e implementa le interfacce Serializable e Clonable. A volte gli array sono chiamati comunemente anche vettori ma è preferibile usare il termine array perchè array e vettori in Java non sono esattamente la stessa cosa (lo vedremo in seguito). Un array, come molti già sapranno, è un insieme di oggetti tutti dello stesso tipo (cioè omogenei tra di loro) distinguibili l'uno dall'altro in base a un indice o posizione. Ogni oggetto che fa parte dell'insieme è detto elemento dell'array mentre il numero degli elementi dell'array (detto dimensione) una volta fissato non può più essere cambiato. Di solito gli elementi di un array vengono memorizzati in locazioni contigue di memoria. L'indice (intero che può essere una costante o un'espressione numerica) che serve per accedere ad ogni singolo elemento deve essere un valore valido, cioè compreso tra 0 e la dimensione dell'array – 1, altrimenti il linguaggio genera una eccezione di tipo ArrayIndexOutOfBoundsException. Fig. 1 – La gerarchia delle eccezioni per un array La dichiarazione di un array in Java si scrive in questo modo: int[] a; Se dichiariamo l'array senza allocarlo e poi cerchiamo di accedere ad uno dei suoi elementi (magari scrivendo per esempio, subito dopo la dichiarazione, l'istruzione System.out.println(a[4])), otteniamo l'eccezione NullPointerException, perchè, in effetti, una volta dichiarato l'array il valore contenuto in a è appunto null. Fig. 2 – Un array appena dichiarato (il pallino nero rappresenta il valore speciale null) Possiamo dichiarare e creare l'array con l'operatore new: int[] a = new int[5]; In questo momento tutti gli elementi dell'array sono uguali a 0 (per un array di interi, uguali a spazi per un array di char, uguali a false per un array di boolean ecc). ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 2/19 Fig. 3 – L'array a allocato Possiamo semplificare la figura in questo modo: Fig. 4 – Indichiamo solo il nome del reference e le locazioni cui punta Fig. 5 – Altra rappresentazione dell'array usando la notazione UML Possiamo caricare i valori dei singoli elementi dell'array usando un opportuno algoritmo: for (int i = 0; i < a.lenght; i++) a[i] = 2*i + 2; Il numero di elementi di un array (o dimensione) in Java si indica con length ed è una proprietà mentre non esiste un metodo o una proprietà in C++ (possiamo comunque calcolare dinamicamente la dimensione di un array usando la funzione sizeof() e l'espressione sizeof(a)/sizeof(int) nel caso di un vettore di interi). Il numero di caratteri di una stringa in Java e in C++ invece è restituito dal metodo lenght() (in C++ esiste comunque anche il metodo size() per il numero di caratteri di una stringa). Abbiamo detto che la dimensione una volta fissata non si può cambiare: tuttavia la dimensione può anche essere una variabile come indica il seguente esempio: int[] a; // Dichiarazione dell'array a int n=5; // Dimensione dell'array a=new int[n]; // Creazione // Inizializzazione for (int i=0; i<a.length; i++) a[i]=2*i+2; Da questo momento in poi però non possiamo più cambiare la dimensione dell'array. Fig. 6 – I valori contenuti nell'array dopo l'esecuzione del ciclo for ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 3/19 Possiamo contestualmente dichiarare e inizializzare i valori dell'array in maniera rapida e diretta: int[] a = {2,4,6,8,10}; Array di oggetti Gli elementi di un array possono anche essere oggetti ad esempio stringhe. Ricordiamo che le stringhe di caratteri sono oggetti della classe String: String s = new String("Questa è una stringa"); Tuttavia il modo più comune di creare una stringa consiste nell'assegnare una costante stringa a un oggetto di tipo String: String s = "Questa è una stringa"; Per creare in maniera rapida un array di stringhe, possiamo quindi scrivere: String[] winx = {“Bloom”,”Stella”,”Musa”,”Flora”,”Tecna”,”Aisha”}; Fig. 7 – Un array di stringhe Se volessimo invece memorizzare maggiori informazioni negli oggetti, allora dobbiamo creare una classe di supporto (Fata, fonte wikipedia) e istanziare gli oggetti che faranno parte dell'array: /* * Fata.java */ package winxclub; import java.util.GregorianCalendar; /** * * @author maurizio */ public class Fata { String nome; String creataDa; String editore; String apparizione; String voceOrigin; String luogoDiNascita; ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 4/19 GregorianCalendar dataDiNascita; String occhi; String statoAttuale; String abilita; String alleati; String nemici; String parenti; String base; public Fata(String nome, String luogoDiNascita, GregorianCalendar dataDiNascita, String occhi, String abilita) { this.luogoDiNascita = luogoDiNascita; this.dataDiNascita = dataDiNascita; this.nome = nome; this.occhi = occhi; this.abilita = abilita; } private String dateToString(GregorianCalendar dataDiNascita) { int anno = dataDiNascita.get(Calendar.YEAR); // i mesi si contano da zero, quindi JANUARY=0, FEBRUARY=1 ecc int mese = dataDiNascita.get(Calendar.MONTH)+1; int giorno = dataDiNascita.get(Calendar.DAY_OF_MONTH); String dataStr = giorno+"/"+mese+"/"+anno; return dataStr; } public String toString() { return "Nome "+nome+ ", luogo di nascita "+luogoDiNascita+", data di nascita "+dateToString(this.dataDiNascita)+", occhi "+occhi; } } // fine classe Fata Fig. 8 – Le Winx: da sinistra a destra: Flora, Aisha, Musa, Bloom, Tecna e Stella Ora istanziamo 3 dei 6 oggetti corrispondenti ai nostri personaggi (ipotizziamo che il seguente codice sia contenuto nel metodo statico main di una classe di prova Main): Fata bloom = new Fata("Bloom", "Domino", new GregorianCalendar(1988, 11, 10),"Celesti", "Fiamma del drago"); Fata stella = new Fata("Stella", "Solaria", new GregorianCalendar(1987, 7, 18),"Marroni","Potere del sole e della luna"); ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 5/19 Fata aisha = new Fata("Aisha", "Andros", new GregorianCalendar(1989, 4, 15), "Celesti-blu", "Fluido Morfix"); Creiamo ora l'array winxClub: Fata[] winxClub = new Fata[6]; e assegniamo i valori ai singoli elementi dell'array: winxClub[0] = bloom; winxClub[1] = stella; // Dobbiamo ancora istanziare le altre winx Musa, Flora e Tecna winxClub[5] = aisha; Avremo potuto scrivere il codice in maniera più compatta come abbiamo visto precedentemente: Fata[] winxClub = {bloom, stella, null, null, null, aisha}; In questa situazione non tutti gli elementi sono assegnati: scorrendo quindi l'array in maniera sequenziale, dobbiamo escludere dal conteggio i reference uguali a null. for (int i = 0; i<winxClub.length; i++) if (winxClub[i]!=null) System.out.println(winxClub[i].toString()); Fig. 9 – Un array di oggetti ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 6/19 Collections Framework Una Collection è una struttura dati - un oggetto in sostanza - che contiene riferimenti ad altri oggetti, di solito dello stesso tipo. Nelle prime versioni di Java in realtà nelle Collection era possibile memorizzare oggetti di natura qualunque: per ricavare poi un particolare elemento della collezione era necessario effettuare un cast. Tipicamente le Collection rappresentano dati che formano gruppi ”naturali”, come una mano di poker (Collection di carte), un elenco di brani su un cd (Collection di canzoni), una casella di posta elettronica (Collection di e-mail) o un elenco telefonico (Collection di coppie di tipo nomenumero di telefono). Un Collections Framework è un'architettura unificata per rappresentare e manipolare le Collection. Tutti i Collections Framework contengono i seguenti elementi: Interfacce: Nelle interfacce troviamo per definizione solo le operazioni ammissibili sulle collezioni (metodi astratti). Spetterà poi alle classi concrete implementare i metodi descritti nelle interfacce. Implementazioni: Implementazioni concrete delle interfacce. In pratica, sono strutture dati riutilizzabili. Algoritmi: Metodi che eseguono operazioni utili, come la ricerca e l’ordinamento, all’interno di oggetti che implementano le interfacce. Gli algoritmi sono polimorfi, cioè lo stesso metodo può essere usato in molte differenti implementazioni di una certa interfaccia. In pratica, gli algoritmi sono funzionalità riutilizzabili. Le interfacce Le Core Collections Interfaces descrivono differenti tipi di collezioni, come riportato in figura 10. L’interfaccia Collection è la radice dell'albero (in Java un'interfaccia ne può estendere un'altra) e comprende le interfacce List, Set e SortedSet, mentre Map è la radice dell'interfaccia SortedMap. Alcuni tipi di collezioni permettono la duplicazione di elementi, altri non la permettono. Alcuni sono ordinati e altri non lo sono. Fig. 10 – Core Collection Interfaces ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 7/19 Diamo una breve descrizione delle interfacce: Set = Collezione che non può contenere elementi duplicati. L’interfaccia fornisce un’astrazione del modello matematico di insieme. List = Collezione ordinata (detta anche sequenza), che può contenere elementi duplicati, ciascuno dei quali è identificato da un indice (la posizione). Map = Oggetto che collega chiavi a valori. Una mappa non può contenere chiavi duplicate e ogni chiave può essere collegata al massimo con un valore. Modella il concetto matematico di funzione. SortedSet = E’ un Set che mantiene gli elementi in ordine crescente. Diverse operazioni aggiuntive sono fornite per usufruire dei vantaggi dell’ordinamento. SortedMap = E’ una Map che mantiene il collegamento chiave-valore in ordine crescente di chiave. Le implementazioni Le implementazioni più comunemente utilizzate sono quelle riportate in tabella 1 ma noi studieremo solo Set, List e Map. Ogni implementazione fornisce tutte le operazioni contenute nella sua interfaccia. Diamo una breve descrizione di alcune classi concrete: HashSet = Gli elementi sono memorizzati in ordine sparso, senza alcuna garanzia sull’ordine in cui potranno essere letti. ArrayList = Implementazione di List come array ridimensionabile (è possibile aggiungere ed eliminare elementi). Vector = E' come ArrayList ma i suoi elementi sono Object (inoltre la classe è sincronizzata) HashMap = Implementazione di Map ma gli elementi non sono ordinati Interfaccia Implementazione Set HashSet Strutture dati “storiche” TreeSet LinkedHashSet List Map ArrayList Vector LinkedList Stack HashMap HashTable TreeMap Properties LinkedHashMap Tab. 1 – Rapporto tra Interfacce e implementazioni Interfaccia List e sua implementazione ArrayList Riscriviamo l'esempio precedente usando questa volta la classe ArrayList e il concetto di genericità (generics) introdotto per la prima volta in Java 5. ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 8/19 Consideriamo sempre la classe di supporto Fata dell'esempio precedente e il seguente codice: List<Fata> winxClub = new ArrayList<Fata>(); // dichiarazione e creazione di un ArrayList In questo momento la situazione in memoria è la seguente: Fig. 11 – Situazione dopo aver creato l'oggetto winxClub; in questo momento non ci sono elementi nella struttura dati Non ci sono elementi e la struttura è vuota: System.out.println("il winxclub è vuoto? "+winxClub.isEmpty()); Subito dopo istanziamo un oggetto e aggiungiamolo alla struttura: Fata bloom = new Fata("Bloom", "Domino", new GregorianCalendar(1988, 11, 10),"Celesti", "Fiamma del drago"); winxClub.add(bloom); // aggiungiamo Bloom al winxClub Questa la situazione in memoria: Fig. 12 – L'ArrayList contiene per il momento un solo elemento ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 9/19 Fig. 13 – L'interfaccia List e i suoi metodi astratti Aggiungiamo ancora un elemento: Fata stella = new Fata("Stella", "Solaria", new GregorianCalendar(1987, 7, 18),"Marroni","Potere del sole e della luna"); Fig. 14 – La struttura con due elementi in memoria ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 10/19 Possiamo continuare ad aggiungere elementi in maniera dinamica alla struttura col metodo add() anche senza usare direttamente nomi di variabili istanza: winxClub.add(new Fata("Aisha", "Andros", new GregorianCalendar(1989, 4, 15), "Celesti-blu", "Fluido Morfix")); Nulla vieterebbe di aggiungere ancora una volta un elemento aggiunto precedentemente: winxClub.add(stella); // abbiamo un elemento duplicato E' possibile farsi dare il numero di elementi della struttura col metodo size() (size() tiene conto anche degli elementi duplicati): System.out.println(winxClub.size()); Osserviamo che il metodo add() restituisce un valore booleano true se l'inserimento ha successo, false in caso contrario: if(winxClub.add(bloom)==true) System.out.println(“Inserimento effettuato”); else System.out.println(“Impossible inserire l'elemento”); Possiamo scorrere la struttura con un oggetto di tipo Iterator for (Iterator i=winxClub.iterator(); i.hasNext(); ) System.out.println(i.next().toString()); oppure con un ciclo for generalizzato: for (Fata f : winxClub) System.out.println(f.toString()); oppure con un ciclo for con indice: for (int i=0; i<winxClub.size(); i++) System.out.println(winxClub.get(i).toString()); Possiamo eliminare un elemento (il primo che incontriamo se ce n'è più di uno) dalla struttura col metodo remove(): boolean b = winxClub.remove(stella); if (b) System.out.println(“Eliminata stella dal winxClub”); else System.out.println(“Impossibile eliminare stella”); Viene ovviamente decrementato il valore restituito da size(). Oppure possiamo passare al metodo remove() la posizione dell'elemento che intendiamo cancellare; la posizione deve essere un valore compreso tra 0 e size()-1, altrimenti il programma genera una eccezione di tipo IndexOutOfBoundsException. Questa volta il metodo restituisce un reference all'oggetto eliminato invece che un valore booleano: Fata f = winxClub.remove(2); if (f==null) System.out.println(“Impossibile eliminare l'elemento di posizione 2”); else System.out.println(“Elemento eliminato ”+f.toString()); ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 11/19 Creiamo ora una winx fittizia (elemento “dummy”) e aggiungiamola alla lista: Fata g = new Fata("Fata dummy","Luogo di nascita dummy", new GregorianCalendar(1988,1,1),"Colore dummy","Abilità dummy"); winxClub.add(g); Ora creiamo musa e sostituiamola all'elemento “dummy” col metodo set(): Fata musa = new Fata("Musa","Melody",new GregorianCalendar(1988,4,30),"Non noto","Potere della musica"); int d = winxClub.size(); winxClub.set(d-1,musa); Gli elementi dell'arraylist sono individuabili in base alla posizione; per accedere a un singolo elemento possiamo usare il metodo get(): Fata h = winxClub.get(2); if (h!=null) System.out.println(h.toString()); else System.out.println(“Il reference è null”); Ci sarebbero molti altri metodi da analizzare ma non abbiamo tempo per studiarli tutti. Interfaccia Set e sua implementazione HashSet L'interfaccia Set contiene metodi ereditati da Collection ma aggiunge la limitazione che proibisce elementi duplicati. La piattaforma Java contiene 3 implementazioni generali di Set ma HashSet è l'implementazione con le prestazioni migliori ma non abbiamo idea di quale sia l’ordine degli elementi quando si itera su di essi. Fig. 15 – Interfaccia Set L'implementazione HashSet si basa sul concetto di funzione di Hash (se si desidera approfondire questo argomento, consigliamo l'ottimo articolo del prof. Alessandro Bugatti disponibile all'indirizzo http://www.imparando.net/elearning/claroline/backends/download.php? url=L0hhc2hfdGFibGUvSGFzaC5wZGY%3D&cidReset=true&cidReq=INF0003) ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 12/19 Wikipedia (http://it.wikipedia.org/wiki/Hash) riporta la seguente definizione: «Nel linguaggio matematico e informatico, la funzione hash è una funzione non iniettiva che mappa una stringa di lunghezza arbitraria in una stringa di lunghezza predefinita.» Le funzioni di hashing hanno una notevole importanza nel campo della crittografia, nell'ambito dei database e nella trasmissione dei dati. La funzione di hashing deve essere progettata in modo da ridurre al minimo le collisioni (si verifica una collisione quando due stringhe di input producono lo stesso valore di hash) e, anche qualora queste si verificassero, devono esistere delle politiche di gestione delle collisioni. Il nostro esempio questa volta (capiremo più avanti perchè) riguarda i supereroi della casa editrice Marvel (i Vendicatori, con le varianti New Avengers, Mighty Avengers, fig. 17 e fig. 18 rispettivamente). class SuperEroe { String nome; String editore; String alterEgo; String creatoDa; String primaApparizione; int altezza; // in cm int peso; // in kg String occhi; String capelli; String statoAttuale; String abilita; String alleati; String nemici; String parenti; public SuperEroe(String nome, String alterEgo, String abilita) { this.nome = nome; this.alterEgo = alterEgo; this.abilita = abilita; } public String toString() { return "nome: "+nome+", alter ego: "+alterEgo+", abilità: "+abilita; } } Creaimo ora l'HashSet nel seguente modo: Set<SuperEroe> newAvengers = new HashSet<SuperEroe>(); Non vi sono elementi nell'HashSet in questo momento: provvediamo quindi ad aggiungerne tre: SuperEroe spiderman = new SuperEroe("Spider-Man","Peter Parker","Tutte le capacità di un ragno moltiplicate alla taglia umana (forza, velocità, agilità), senso di ragno che lo avverte dei pericoli"); newAvengers.add(spiderman); SuperEroe wolverine = new SuperEroe("Wolverine","James Howlett (Logan)","fattore rigenerante, artigli protrattili, sensi sviluppatissimi, forza e agilità notevoli, esperto di arti marziali"); newAvengers.add(wolverine); SuperEroe ironMan = new SuperEroe("Iron Man","Antony Edward (Tony) Stark","Genio scientifico, capacità dell'armatura: superforza, semi-invulnerabilità, ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 13/19 volo, raggi repulsori, armi da fuoco e missili di varia natura"); newAvengers.add(ironMan); Il codice precedente non è dissimile da quello usato con le liste (il metodo add() infatti è polimorfico) e la rappresentazione in memoria, come si può vedere nella fig. 16, non è neanche molto diversa, tuttavia con i set non esiste il concetto di posizione dell'elemento. Questo significa inoltre che l'esecuzione di un ciclo di lettura degli elementi come il seguente, se lanciato più volte, può produrre risultati differenti: // Visualizziamo tutti gli elementi for (SuperEroe se : newAvengers) System.out.println(se.toString()); Fig. 16 – 3 dei nuovi vendicatori ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 14/19 Fig. 17 – Copertina del primo numero “The New Avengers (I nuovi vendicatori)“ Bulk operations Le bulk operations (letteralmente “operazioni in blocco”) sono particolarmente utili se applicate all’interfaccia Set, perché permettono di applicare su insiemi le operazioni algebriche di unione (addAll()), differenza (removeAll()) e intersezione (retainAll()), oltre a permettere di verificare se un dato insieme è sottoinsieme di un altro (containsAll()). Se s1 e s2 sono set, allora: s1.addAll(s2) Trasforma s1 nell'unione degli elementi di s1 ed s1 (coincide con l'unione insiemistica, cioè trova l'insieme degli elementi di s1 ed s2). s1.removeAll(s2) Trasforma s1 nella differenza insiemistica (asimmetrica) di s1 ed s2 (cioè calcola l'insieme degli elementi di s1 che non appartengono ad s2). s1.retainAll(s2) Trasforma s1 nell'intersezione di s1 ed s2 (cioè il set contiene tutti gli elementi di s1 ed s2 che sono comuni). I metodi addAll(), removeAll() e retainAll() restituiscono true se s1 è stata modificata in seguito all’esecuzione dell’operazione. s1.containsAll(s2) Restituisce true se s2 è sottoinsieme di s1. Per calcolare l'unione, l'intersezione o la differenza insiemistica di due set in modo non distruttivo (senza modificare i set), l'oggetto chiamante deve copiare il set prima di chiamare l'operazione bulk. Per provare alcuni dei metodi sopra elencati, consideriamo il nuovo set relativo ai Potenti Vendicatori (The Mighty Avengers): Set<SuperEroe> mightyAvengers = new HashSet<SuperEroe>(); ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 15/19 SuperEroe quickSilver = new SuperEroe("Quicksilver","Pietro Django Maximoff","Supervelocità"); SuperEroe stature = new SuperEroe("Stature","Cassandra Eleanor (Cassie) Lang","Può diventare alta fino a 30 metri o piccola come una formica, può emettere scariche di energia"); Aggiungiamo i 3 Potenti Vendicatori: mightyAvengers.add(quickSilver); mightyAvengers.add(stature); mightyAvengers.add(ironMan); Vogliamo l'intersezione tra newAvengers e mightyAvengers // Copia del set newAvengers Set<SuperEroe> intersezione = new HashSet<SuperEroe>(newAvengers); intersezione.retainAll(mightyAvengers); System.out.println("Intersezione tra NewAvengers e MightyAvengers"); for (SuperEroe se : intersezione) System.out.println(se.toString()); Il risultato, come è prevedibile, è ironMan. Lasciamo al lettore il compito di creare eventualmente altri gruppi e di provare le altre operazioni insiemistiche, magari facendo delle prove con i Dark Avengers (fig. 19), guardando su www.wikipedia.it o www.wikipedia.en. Interfaccia Map e sua implementazione HashMap Java contiene 3 implementazioni generali di Map mentre l'implementazione migliore è HashMap che però non fornisce una garanzia sull'ordine degli elementi, come si può intuire rileggendo la sezione relativa all'interfaccia Set. Per fare un esempio di HashMap, consideriamo come chiave di accesso agli elementi della mappa il nome del supereroe. Mappiamo cioè i nomi (stringhe) con gli oggetti (di tipo SuperEroe). Istanziamo una mappa: Map<String, SuperEroe> newAvengers = new HashMap<String, SuperEroe>(); ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 16/19 Fig. 18 – Copertina del n. 1 di “The Mighty Avengers (I Potenti Vendicatori)” Fig. 19 – Copertina del n. 1 di “Dark Avengers” ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 17/19 Per aggiungere elementi alla mappa, scriviamo per esempio: SuperEroe spiderman = new SuperEroe("Spider-Man","Peter Parker","Tutte le capacità di un ragno moltiplicate alla taglia umana (forza, velocità, agilità), senso di ragno che lo avverte dei pericoli"); // Aggiungiamo spiderman alla mappa newAvengers.put(spiderman.nome,spiderman); Questa volta usiamo il metodo put() che richiede due argomenti (una chiave e un valore). Possiamo aggiornare il valore degli attributi dell'oggetto mappato dalla chiave usando ancora il metodo put(): // Aggiorniamo le abilità di Spider-Man spiderman.abilita = "Forza, velocità, agilità, senso di ragno"; newAvengers.put(spiderman.nome,spiderman); // Controlliamo se la variazione è stata effettuata System.out.println(spiderman.toString()); Aggiungiamo un nuovo vendicatore: SuperEroe wolverine = new SuperEroe("Wolverine","James Howlett (Logan)","Fattore rigenerante, artigli protrattili, sensi sviluppatissimi, forza e agilità notevoli, esperto di arti marziali"); newAvengers.put(wolverine.nome, wolverine); Fig. 20 – Rappresentazione di una mappa (nella figura sono state rappresentate le chiavi) Il metodo values() restituisce la Collection dei valori: Collection<SuperEroe> elencoNewAvengers = newAvengers.values(); ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 18/19 Visualizziamo gli oggetti: for (SuperEroe se : elencoNewAvengers) System.out.println(se.toString()); Fig. 21 – L'interfaccia Map Possiamo anche visualizzare le chiavi (l'insieme delle chiavi è proprio un Set): Set<String> elencoNomi = newAvengers.keySet(); // Elenco delle chiavi for (String nome : elencoNomi) System.out.println(nome); Per rimuovere un elemento della mappa, usiamo il metodo remove() che ha come argomento la chiave: if (newAvengers.remove(wolverine.nome)!=null) System.out.println("Eliminato "+wolverine.nome); else System.out.println("Impossibile eliminare "+wolverine.nome); Per cercare un super eroe nella mappa, usiamo il metodo get() che vuole come argomento la chiave (stringa): SuperEroe x = newAvengers.get("Spider-Man"); // Se l'elemento non c'è nella mappa, get restituisce null if (x==null) System.out.println("Il super eroe non c'è nella mappa"); else System.out.println(x.toString()); Come al solito, il metodo size() restituisce il numero degli elementi della mappa: System.out.println(newAvengers.size()); E' possibile inoltre sapere se una certa chiave è contenuta nella mappa: // Il metodo containsKey() restituisce true o false System.out.println(newAvengers.containsKey("Iron Man")); oppure se un certo oggetto è contenuto nella mappa: System.out.println(newAvengers.containsValue(x)); ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009 Java Java Collections Framework Pag. 19/19 Fig. 22 – Spider-Man rivela al mondo la sua identità segreta (Civil War n. 1, miniserie Marvel) Fonti di riferimento Java Tutorial, Corso rapido quarta edizione, AV, McGraw-Hill Java Collection Framework, John Zuckowski, http://www.ibm.com/developerworks/edu/j-dw-javacoll-i.html Wikipedia (en e it), http://www.wikipedia.org Java Riassunto, Francesco Galgani, http://www.guella.it/universita/javariassunto.pdf Informatica Programmazione in Java, F. Scorzoni, Loescher ITIS Castelli, BS Maurizio Cozzetto Brescia, 18 nov 2009