Java Collection Framework File - e-Learning

6/3/2014
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java
Collection Framework
Daniela Micucci
[email protected]
Introduzione
• Una collezione – a volte chiamata container ‐ è un elemento “contenitore” di oggetti chiamati elementi
• La necessità di strutture dati che raggruppino oggetti è comune a molte applicazioni
– Ad esempio:
• mail folder (collezione di mail) , • rubriche (collezione di associazioni nome‐numero di telefono) • ...
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
2
1
6/3/2014
Java Collection Framework
• È un insieme di interfacce e di classi che supportano tre tipi di collezioni:
– Insiemi
• Collezioni di elementi che non ammettono duplicati
– Liste
• Collezioni ordinate di elementi • Chiamate anche sequenze
– Mappe
• Collezione di coppie <chiave, valore>
– Il valore è quindi l’elemento
– La chiave è usata per inserire l’elemento e per recuperare l’elemento
• Le chiavi non ammettono duplicati
• Le mappe sono anche chiamate dizionari
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
3
Java Collection Framework
• Il Java Java Collection Framework contiene
– Un insieme di interfacce (e classi astratte) che specificano un insieme di funzionalità
– Un insieme vasto di collezioni già implementate che realizzano liste, insiemi e mappe
– Diverse implementazioni per ciascuna tipologia di collezione
• Le strutture dati sono contenitori generici per gli oggetti
– Fino alla versione 1.4 si usava la classe Object
– Dalla versione 1.5 è stato aggiunto il supporto ai generici
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
4
2
6/3/2014
Organizzazione
•
Liste e Insiemi: •
Mappe: – implementano l’interface Collection<E>
– implementano l’interface Map<K,V>
«interface»
Collection
«interface»
Set
«interface»
Map
«interface»
List
AbstractCollection
«interface»
SortedMap
«interface»
SortedSet
AbstractMap
AbstractList
AbstractSet
AbstractSequentialList
Set - Insiemi
TreeSet
Software Architecture Lab
www.sal.disco.unimib.it
List - Liste
HashSet
Vector
ArrayList
Map - Mappe
LinkedList
TreeMap
HashMap
Programmazione con Java: Collection Framework
5
L’interface Collection<E>
• L’interfaccia Collection<E> specifica le operazioni di base che tutte le collezioni di elementi devono implementare (Liste e Insiemi)
• Nonostante non sia espressamente richiesto dall’interfaccia, qualunque classe che implementi l’interfaccia Collection<E> dovrebbe avere almeno due costruttori: – Senza parametri e che crea un oggetto di tipo Collection<E>
vuoto – Con un parametro di tipo Collection<? extends E> che crea un oggetto di tipo Collection<E> contenente gli stessi elementi dell’argomento
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
6
3
6/3/2014
L’interface Collection<E>
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
7
L’interface Collection<E>
• I metodi opzionali devono comunque essere implementati – Possono deviare dalla semantica attribuita – Se deviano dalla semantica fornendo una implementazione triviale, devono generare una UnsupportedOperationException
• Se, per qualche motivo, non si è interessati a definire un’implementazione vera e propria • Una UnsupportedOperationException è una RunTimeException e quindi non è necessario gestirla o dichiararla in una clausola throws
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
8
4
6/3/2014
Insiemi: l’interface Set<E>
Insieme: collezione di elementi che non ammette duplicati
• L’interface Set<E> definisce le operazioni che un insieme in quanto tale deve offrire
• Per evitare che esistano duplicati all’interno della collezione, l’interface Set<E> cambia la semantica di alcuni metodi ereditati da Collection<E>
– Due elementi e1 e e2 sono considerati duplicati e quindi non possono appartenere allo stesso set se e solo se e1.equals(e2) == true
• Non ha bisogno di definire ulteriori operazioni
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
9
Insiemi: l’interface Set<E>
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
10
5
6/3/2014
Liste: l’interface List<E>
Lista: collezione ordinata di elementi anche duplicati
• L’interface List<E> definisce le operazioni che una lista in quanto tale deve offrire
• L’interface List<E> cambia la semantica di alcuni metodi ereditati da Collection<E>
• Aggiunge nuovi metodi in modo da poter gestire l’indicizzazione degli elementi (e quindi l’ordinamento)
– Avere un accesso posizionale agli elementi • Tramite indice intero che parte da 0
– Ricercare un elemento e ottenere la sua posizione
– Eseguire operazioni in un determinato intervallo di List
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
11
Liste: l’interface List<E>
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
12
6
6/3/2014
Liste: l’interface List<E>
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
13
Mappe: l’interface Map<K,V>
Mappa: collezione di coppie <chiave, valore> con chiavi non duplicate
• L’interface Map<K,V> definisce le operazioni che una mappa
in quanto tale deve offrire
• I metodi di aggiunta coppie devono verificare che la chiave della nuova coppia non sia già presente nella mappa
– Ogni chiave può mappare al massimo un valore
– Una chiave k1 è considerata duplicata se
containsKeys(k1) restituisce true
– Il che vuol dire che esiste una chiave k2 tale che k2.equals(k1) == true
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
14
7
6/3/2014
Mappe: l’interface Map<K,V>
• Nonostante non sia espressamente richiesto dall’interfaccia, qualunque classe che implementi l’interfaccia Map<K,V>
dovrebbe avere almeno due costruttori: – Senza parametri e che crea un oggetto di tipo Map<K,V> vuoto – Con un parametro di tipo Map<K,V> che crea un oggetto di tipo Map<K,V> contenente gli stessi elementi dell’argomento
• Definisce almeno i metodi per
–
–
–
–
Inserire elementi con chiave
Recuperare/rimuovere gli elementi tramite chiave
Verificare se una chiave è già presente
Recuperare tutte le chiavi/valori
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
15
Mappe: l’interface Map<K,V>
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
16
8
6/3/2014
Collezioni ordinate
• Le classi che implementano l’interface List implicitamente definiscono una sequenza ordinata di elementi
• Map e Set sono collezioni non ordinate
• Per avere un ordinamento anche su mappe e insiemi, occorre che le implementazioni concrete derivino rispettivamente da
– SortedMap: è una Map che mantiene il collegamento chiave‐valore in ordine crescente di chiave
– SortedSet : è un Set che mantiene gli elementi in ordine crescente Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
17
Interface SortedSet<E>
• È un Set che mantiene gli elementi ordinati in ordine crescente
• Gli insiemi ordinati sono utilizzati per realizzare insiemi naturalmente ordinati
– Una lista di parole
– Una lista di persone
– …
«interface»
Collection
«interface»
Set
«interface»
SortedSet
• Gli elementi sono ordinati – Secondo il loro ordine naturale o – Mediante un Comparator (in genere fornito in fase di instanziazione del set)
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
TreeSet
18
9
6/3/2014
Ordinamento naturale
• L’ordinamento naturale, come dice la parola, è quello che uno si aspetta
– Banane, mele, pere, …
– 1, 5, 23
– 12/05/2012, 01/06/2012, …
• Dal punto di vista implementativo, un insieme di oggetti possono essere ordinati naturalmente se la classe che li definisce implementa l’interface Comparable
public interface Comparable<T> {
public int compareTo(T o);
}
Programmazione con Java: Collection Framework
Software Architecture Lab
www.sal.disco.unimib.it
19
In metodo compareTo
• Dati due oggetti o1 e o2 istanziati a partire da una classe che implementa l’interface Comparable
o1.compareTo(o2)
restituirà:
0
Se o1 e o2 sono ‘uguali’
Intero negativo
Se o1 è più piccolo di o2
Intero positivo
Se o1 è più grande di o2
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
20
10
6/3/2014
Esempio
public class DemoCompare {
public static void main(String a[]){
String s1 = new String("a");
String s2 = new String("b");
System.out.println(s1.compareTo(s2));
System.out.println(s2.compareTo(s1));
s2 = new String("a");
System.out.println(s1.compareTo(s2));
}
}
Output:
‐1
1
0
• Stessi risultati per altre classi predefinite come Date e Integer
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
21
Esempio: classe personalizzata
public class Persona implements Comparable<Persona> {
private String cognome;
private String nome;
private String eMail;
public Persona(String cognome, String nome, String eMail) {
this.cognome = cognome;
this.nome = nome;
this.eMail = eMail;
}
@Override
public int compareTo(Persona altra) {
int val = cognome.compareTo(altra.cognome);
if(val != 0)
return val;
else
return nome.compareTo(altra.nome);
}
//
…
}
• Classe completa
Software Architecture Lab
www.sal.disco.unimib.it
Confronto solo su cognome e poi nome
public class DemoComparable {
public static void main(String a[]){
Persona p1 = new Persona("Rossi", "Mario", "[email protected]");
Persona p2 = new Persona("Rossi", "Marco", "[email protected]");
System.out.println(p1.compareTo(p2)); //stampa 6
System.out.println(p2.compareTo(p1)); //stampa -6
p2 = new Persona("Rossi", "Mario", "[email protected]");
System.out.println(p1.compareTo(p2)); //stampa 0
}
}
Programmazione con Java: Collection Framework
22
11
6/3/2014
Coerenza ordinamento naturale/equals
• L’ordinamento naturale per una classe C è detto essere coerente
con l’uguaglianza (equals) se e solo se
e1.compareTo(e2) == 0
ha lo stesso valore booleano di e1.equals(e2) per ogni istanza e1 e e2 di C
• È importante mantenere la coerenza poiché alcuni sorted set si comportano stranamente se non viene mantenuta la coerenza
– Un sorted set non ammette duplicati in termini di equals
– Si provi ad inserire in un sorted set due elementi a e b tali che
(!a.equals(b) && a.compareTo(b) == 0)
• Il secondo non viene inserito!
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
23
Esempio: classe personalizzata
Confronto solo su cognome e poi nome
• Classe completa
Software Architecture Lab
www.sal.disco.unimib.it
public class Persona implements Comparable<Persona> {
private String cognome; private String nome;
private String eMail;
// …
@Override
public boolean equals(Object obj) {
// …
Persona other = (Persona) obj;
if (cognome == null) {
if (other.cognome != null)
return false;
} else if (!cognome.equals(other.cognome))
return false;
if (nome == null) {
if (other.nome != null)
return false;
} else if (!nome.equals(other.nome))
return false;
return true;
}
@Override
public int compareTo(Persona altra) {
int val = cognome.compareTo(altra.cognome);
if(val != 0)
return val;
else
return nome.compareTo(altra.nome);
}
// …
}
Programmazione con Java: Collection Framework
24
12
6/3/2014
Ordinamento mediante Comparator
• Se si vuole specificare un ordinamento diverso da quello naturale, si realizza un Comparator: – Una interface che impone un ordinamento totale su una collezione di oggetti che è diverso da quello naturale
public interface Comparator<T> {
public int compare(T o1, T o2);
//…
}
• Stesso comportamento del metodo compareTo
• Lo specifico in fase di instaziazione della collezione ordinata
– Esempio: TreeSet(Comparator<? super E> comparator)
costruisce un nuovo set ordinato in accordo al comparator specificato
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
25
Ordinamento mediante Comparator
• Se si vuole specificare un ordinamento diverso da quello naturale, si realizza un Comparator: – Una interface che impone un ordinamento totale su una collezione di oggetti che è diverso da quello naturale
public interface Comparator<T> {
public int compare(T o1, T o2);
//…
}
• Stesso comportamento del metodo compareTo
• Coerenza ordinamento/equals dovrebbe essere garantita
• Lo specifico in fase di instaziazione della collezione ordinata
– Esempio: TreeSet(Comparator<? super E> comparator)
costruisce un nuovo set ordinato in accordo al comparator specificato
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
26
13
6/3/2014
Esempio Comparator
• Classe che implementa Comparator per confrontare due persone
import java.util.Comparator;
public class ComparatorPersone implements Comparator<Persona> {
@Override
public int compare(Persona o1, Persona o2) {
int val = o1.getCognome().compareTo(o2.getCognome());
if(val != 0)
return val;
else
return o1.getNome().compareTo(o2.getNome());
}
Confronto solo su cognome e poi nome
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
27
Interface SortedSet<E>
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
28
14
6/3/2014
Interface SortedMap<K,V>
• È una Map che mantiene le chiavi ordinate in ordine crescente
«interface»
Map
– Analoga a SortedSet
• Le mappe ordinate sono utilizzate per realizzare insiemi naturalmente ordinati di chiavi/valore
– Un dizionario
– Un elenco telefonico
– …
«interface»
SortedMap
• Come per l’interface SortedSet, le chiavi sono ordinate – Secondo il loro ordine naturale o – Mediante un Comparator (in genere fornito in fase di instanziazione della map)
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
TreeMap
29
Interface SortedMap<K,V>
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
30
15
6/3/2014
Implementazioni disponibili
• I tipi di collezioni possono essere implementati in diverse maniere
Implementazioni disponibili
Interface
Hash table
Set
HashSet
List
Map
Software Architecture Lab
www.sal.disco.unimib.it
Array ridimensionabile
Albero
ordinato
Liste concatenate
TreeSet
ArrayList
HashMap
LinkedList
TreeMap
Programmazione con Java: Collection Framework
31
Caratteristiche delle implementazioni
• Le liste concatenate (o linked list) sono liste realizzate mediante puntatori
• Gli array ridimensionabile (o resizable array) sono liste realizzate tramite array di reference
• Gli alberi ordinati (o sorted tree ) sono alberi bilanciati ed ordinati realizzati mediante puntatori
• Le tabelle di hash (o hash table) sono tabelle realizzate mediante delle funzioni hash
– Vediamo le hash table cosa sono…
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
32
16
6/3/2014
Hashing
• L'Hashing è la trasformazione di una stringa di caratteri in una sequenza di lunghezza fissa più breve denominata hash (o chiave)
• Una funzione di hash mappa quindi una stringa di lunghezza arbitraria in una stringa di lunghezza predefinita
Il gatto
Funzione di hash
DM040709
Il gatto mangia
il topo
Funzione di hash
04LM0709
Il gatto mangia
il pesce
Funzione di hash
1703DL08
• L'Hashing è utilizzato per indicizzare e recuperare gli elementi di un database – È più veloce trovare l’elemento mediante una chiave più corta piuttosto che il suo valore originale
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
33
Hash table
• Una hash table o hash map è una struttura dati che usa una funzione di hash per mettere in corrispondenza una data chiave (per esempio il nome di una persona) con un dato valore (ad esempio il suo numero di telefono)
• Di conseguenza, una hash table realizza un array associativo
– La funzione di hash è utilizzata per trasformare la chiave nell’indice (l’hash) di un array di elementi dove il valore corrispondente alla chiave sarà ricercato
chiavi
funzione
di hash
indice (o hash)
valori
00
Mario Rossi
Giorgio Bianchi
Piero Verdi
01
02‐1234567
02
02‐12495611
….
…
49
02‐34234567
50
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
34
17
6/3/2014
Caratteristiche funzione di hash
• Collisione
– Due chiavi a cui viene calcolato lo stesso hash
• Fattore di carico (load factor) – Calcolato come Celle libere/Elementi presenti
– Quanta probabilità ha un nuovo elemento di collidere con uno già presente nella tabella
– È bene dunque mantenere il load factor il più basso possibile (di solito un valore di 0.75 è quello ottimale) per ridurre al minimo il numero di collisioni
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
35
Implementazioni disponibili
• Come detto, esistono disponibili diverse implementazioni delle collezioni
• Ogni implementazione ha i suoi punti di forza o di debolezza rispetto alla struttura dati utilizzata
• Quando si deve selezionare un’implementazione occorre appunto analizzarne proprio i pro/contro
• … vediamone alcuni
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
36
18
6/3/2014
Set: esempi di implementazioni
• TreeSet<E>
«interface»
Collection
– Conviene se si ha necessità di mantenere un ordinamento tra gli elementi
– L’implementazione è simile ad un albero binario, che viene tenuto bilanciato in fase di inserimento
«interface»
Set
AbstractCollection
«interface»
SortedSet
• HashSet<E>
– Gli elementi sono memorizzati in ordine sparso, senza alcuna garanzia sull’ordine in cui potranno essere letti
– È implementata usando una hash table
– Conviene se si hanno prevalentemente accessi diretti agli elementi
Software Architecture Lab
www.sal.disco.unimib.it
AbstractSet
Set - Insiemi
TreeSet
HashSet
Programmazione con Java: Collection Framework
37
Liste: esempi di implementazioni
• ArrayList<E>
– È l’implementazione più usata
– Conviene se si hanno prevalentemente accessi posizionali agli elementi (diretti)
«interface»
Collection
«interface»
List
• Vector<E>
– La prima collezione definita nel linguaggio
– Alternativa a ArrayList
• LinkedList<E>
– Lista linkata bidirezionale e permette di scorrere gli elementi partendo sia dall’inizio che dalla fine
– Conviene se si hanno prevalentemente cancellazioni (veloce perché si cambiano solo i collegamenti fra nodi della lista
– Accedere all’i‐esimo elemento è un’operazione lenta AbstractList
AbstractSequentialList
List - Liste
Vector
ArrayList
LinkedList
• infatti devono essere percorsi tutti gli elementi precedenti
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
38
19
6/3/2014
Mappe: implementazioni
• HashMap<K,V>
«interface»
Map
– conviene se si hanno accessi diretti agli elementi – tempo di accesso costante
• TreeMap<K,V>
«interface»
SortedMap
AbstractMap
– conviene se si ha necessità di mantenere un ordinamento tra gli elementi
– tempo di accesso logaritmico
Map - Mappe
TreeMap
Software Architecture Lab
www.sal.disco.unimib.it
HashMap
Programmazione con Java: Collection Framework
39
Tip #1
• Le classi contengono metodi che specificano di lanciare numerose eccezioni
– Sono tutte comunque unchecked, utili per il debug
• In classi implementate possono essere viste come run‐time error
• Quando si codifica una collezione from scratch, occorre lanciare tutte le eccezioni che l’interfaccia implementata dichiara di lanciare
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
40
20
6/3/2014
ITERATORI
Programmazione con Java: Collection Framework
41
L’interface Iterator
• Un iteratore è un oggetto che permette di effettuare una visita degli elementi di una collezione (qualsiasi classe che implementa Collection)
• Iterator è una interface così definita:
public interface Iterator<E> {
public boolean hasNext();
public E next();
public void remove(); //opzionale
}
– hasNaxt
• restituisce true se esiste un elemento successivo
– next
• si posiziona sull’elemento successivo e lo restituisce
– remove
• rimuove l’elemento attuale
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
42
21
6/3/2014
L’interface Iterator
• Si ottiene un iteratore di una collezione invocando il suo metodo iterator() che restituisce un oggetto di tipo Iterator
– Hint: ogni volta che voglio iterare, devo farmi ridare l’iteratore
• L’interface Map non espone il metodo iterator()
• È possibile solo ottenere un iteratore per le chiavi e i valori
– keySet() che restituisce un Set
– values() che restituisce una Collection
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
43
Esempio di utilizzo
import java.util.ArrayList;
import java.util.Iterator;
public class Demo01 {
public static void main(String[] args) {
ArrayList<String> lista = new ArrayList<String>();
lista.add("uno");
lista.add("due");
Iterator<String> i = lista.iterator();
while(i.hasNext()){
String el = i.next();
System.out.println(el);
}
i = lista.iterator();
i.next();
//rimuove l’ultimo elemento restituito da next
i.remove();
System.out.println(lista);
}
}
Output:
uno
due
[due]
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
44
22
6/3/2014
Iterator per le liste: ListIterator
• ListIterator estende Iterator e i metodi ereditati si comportano analogamente
public interface ListIterator<E> extends Iterator<E>{
public boolean hasPrevious();
public E previous();
public int nextIndex();
public int previousIndex();
public void set(E e); //opzionale
public void add(E e); //opzionale
}
•
hasPrevious e previous sono analoghe a hasNext e next
–
–
•
Le prime si riferiscono all’elemento prima del cursore (implicito), le ultime all’elemento dopo il cursore
previous muove il cursore all’indietro, next in avanti
nextIndex restituisce l’indice dell’elemento che sarebbe restituito dall’invocazione della chiamata a next, perviousIndex ad una chiamata a previous
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
45
ESEMPI DI CLASSI
Programmazione con Java: Collection Framework
46
23
6/3/2014
Interface List: Esempio ArrayList
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class DemoPersonaArrayList {
public static void main(String a[]){
List<Persona> lista = new ArrayList<Persona>();
lista.add(new Persona("Micucci", "Daniela", "[email protected]"));
lista.add(new Persona("Denaro", "Giovanni", "[email protected]"));
lista.add(new Persona("Tisato", "Francesco", "[email protected]"));
lista.add(new Persona("Sartori", "Fabio", "[email protected]"));
}
}
Iterator<Persona> i = lista.iterator();
while(i.hasNext()){
Persona el = i.next();
System.out.println(el);
}
//Lo inserisce comunque in fondo anche se esiste gia'
lista.add(new Persona("Sartori", "Fabio", "[email protected]"));
System.out.println("Set nuovo: ");
i = lista.iterator();
Output:
while(i.hasNext())
Persona [cognome=Micucci, nome=Daniela]
System.out.println(i.next());
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Tisato, nome=Francesco]
Persona [cognome=Sartori, nome=Fabio]
Set nuovo: Persona [cognome=Micucci, nome=Daniela]
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Tisato, nome=Francesco]
Persona [cognome=Sartori, nome=Fabio]
Persona [cognome=Sartori, nome=Fabio]
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
47
Interface List: Esempio Vector
import java.util.Vector;
import java.util.Iterator;
import java.util.List;
public class DemoPersonaVector {
public static void main(String a[]){
List<Persona> lista = new Vector<Persona>();
lista.add(new Persona("Micucci", "Daniela", "[email protected]"));
lista.add(new Persona("Denaro", "Giovanni", "[email protected]"));
lista.add(new Persona("Tisato", "Francesco", "[email protected]"));
lista.add(new Persona("Sartori", "Fabio", "[email protected]"));
}
Iterator<Persona> i = lista.iterator();
while(i.hasNext()){
Persona el = i.next();
System.out.println(el);
}
//Lo inserisce comunque in fondo anche se esiste gia'
lista.add(new Persona("Sartori", "Fabio", "[email protected]"));
System.out.println("Set nuovo: ");
i = lista.iterator();
Output:
while(i.hasNext())
Persona [cognome=Micucci, nome=Daniela]
System.out.println(i.next());
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Tisato, nome=Francesco]
Persona [cognome=Sartori, nome=Fabio]
Set nuovo: Persona [cognome=Micucci, nome=Daniela]
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Tisato, nome=Francesco]
Persona [cognome=Sartori, nome=Fabio]
Persona [cognome=Sartori, nome=Fabio]
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
48
24
6/3/2014
Interface List: Esempio LinkedList
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.List;
public class DemoPersonaTreeMap {
public static void main(String a[]){
List<Persona> lista = new LinkedList<Persona>();
lista.add(new Persona("Micucci", "Daniela", "[email protected]"));
lista.add(new Persona("Denaro", "Giovanni", "[email protected]"));
lista.add(new Persona("Tisato", "Francesco", "[email protected]"));
lista.add(new Persona("Sartori", "Fabio", "[email protected]"));
}
}
ListIterator<Persona> i = lista.listIterator();
while(i.hasNext()){
Persona el = i.next();
System.out.println(i.next());
}
//Non devo riavvolgere l'iteratore --> i = lista.listIterator();
System.out.println("Set all’indietro: ");
while(i.hasPrevious()){
Persona el = i.previous();
Output:
System.out.println(i.next());
Persona [cognome=Micucci, nome=Daniela]
}
Persona [cognome=Denaro, nome=Giovanni]
//Lo inserisce comunque in fondo anche se esiste gia'
Persona [cognome=Tisato, nome=Francesco]
lista.add(new Persona(
Persona [cognome=Sartori, nome=Fabio]
"Sartori", "Fabio", "[email protected]"));
Set all'indietro: Persona [cognome=Sartori, nome=Fabio]
Persona [cognome=Tisato, nome=Francesco]
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Micucci, nome=Daniela]
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
49
Interface Set: Esempio TreeSet
import java.util.TreeSet;
import java.util.Iterator;
import java.util.Set;
public class DemoPersonaTreeSet {
public static void main(String a[]){
Set<Persona> set = new TreeSet<Persona>();
set.add(new Persona("Micucci", "Daniela", "[email protected]"));
set.add(new Persona("Denaro", "Giovanni", "[email protected]"));
set.add(new Persona("Tisato", "Francesco", "[email protected]"));
set.add(new Persona("Sartori", "Fabio", "[email protected]"));
Iterator<Persona> i = set.iterator();
while(i.hasNext())
System.out.println(i.next());
Elementi ordinati
Elementi duplicati non presenti
//Anche se fosse un omonimo, non lo farebbe inserire: è un Set
set.add(new Persona("Sartori", "Fabio", "[email protected]"));
//Lo inserisce dopo Denaro
set.add(new Persona("Fiamberti", "Francesco", "[email protected]"));
System.out.println("Set nuovo: ");
i = set.iterator();
while(i.hasNext())
System.out.println(i.next());
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
Output:
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Micucci, nome=Daniela]
Persona [cognome=Sartori, nome=Fabio]
Persona [cognome=Tisato, nome=Francesco]
Set nuovo: Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Fiamberti, nome=Francesco]
Persona [cognome=Micucci, nome=Daniela]
Persona [cognome=Sartori, nome=Fabio]
Persona [cognome=Tisato, nome=Francesco]
50
25
6/3/2014
Interface Set: Esempio HashSet
• HashSet utilizza una tabella di hash per memorizzare i suoi elementi
• Indicizza (i.e., calcola l’hash) gli elementi applicando una funzione di hash sull’elemento stesso da inserire
• La hash di ogni elemento da inserire viene calcolata invocando sull’elemento stesso il metodo definito in Object (a meno di non averlo overridato)
public int hashCode()
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
51
Il metodo hashCode: specifiche per la sua implementazione
• Ogni volta che viene invocato sullo stesso oggetto, deve restituire sempre lo stesso valore – A patto che l’oggetto non abbia cambiato di stato
• Se due oggetti sono uguali secondo il metodo equals, l’invocazione al metodo su ognuno dei due oggetti deve dare lo stesso valore
– Coerenza hashcode/equals
– Come abbiamo visto la coerenza ordinamento naturale/equals
• Il metodo hashCode definito in Object restituisce interi differenti per oggetti differenti – È implementato convertendo l’indirizzo di memoria dell’oggetto in un intero
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
52
26
6/3/2014
Esempio con String
• La classe ha effettuato l’override sia di equals che di hashCode garantendo la coerenza hashCode/equals
public class DemoHashCode {
public static void main(String[] args) {
String s1 = new String("Ciao");
String s2 = new String("Ciao");
System.out.println(s1.equals(s2));
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
}
}
S1 == s2  false!
Nonostante questo,
hanno stesso hashcode e sono equals
Output:
true
2100020
2100020 Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
53
Esempio con classe Persona senza override
• La classe ha effettuato l’override di equals, ma non di hashCode
public class DemoHashCode {
public static void main(String[] args) {
Persona p1 = new Persona("Micucci", "Daniela", "[email protected]");
Persona p2 = new Persona("Micucci", "Daniela", "[email protected]");
//abbiamo fatto override di equals che verifica nome e cognome
System.out.println(p1.equals(p2));
//... ma non abbianmo fatto l'override di hashCode
// ---> incoerenza hashCode/equals
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
}
}
Output:
true
1167165921
1442002549
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
54
27
6/3/2014
Esempio con classe Persona corretta
•
Override di hashCode coerente con la def. di equals (solo nome e cognome)
public class Persona implements Comparable<Persona> {
// …
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cognome == null) ? 0 : cognome.hashCode());
result = prime * result + ((nome == null) ? 0 : nome.hashCode());
return result;
}
public class DemoHashCode {
// …
public static void main(String[] args) {
}
Persona p1 = new Persona("Micucci", "Daniela", "[email protected]");
Persona p2 = new Persona("Micucci", "Daniela", "[email protected]");
//abbiamo fatto override di equals che verifica nome e cognome
System.out.println(p1.equals(p2));
//... Con override di hashCode ---> coerenza hashCode/equals
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
}
}
Output:
true
1503986568
1503986568
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
55
Interface Set: Esempio HashSet
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class DemoPersonaTreeSet {
public static void main(String a[]){
Set<Persona> set = new HashSet<Persona>();
set.add(new Persona("Micucci", "Daniela", "[email protected]"));
set.add(new Persona("Denaro", "Giovanni", "[email protected]"));
set.add(new Persona("Tisato", "Francesco", "[email protected]"));
set.add(new Persona("Sartori", "Fabio", "[email protected]"));
Iterator<Persona> i = set.iterator();
while(i.hasNext())
System.out.println(i.next());
Elementi non ordinati
Elementi duplicati non presenti
//Anche se fosse un omonimo, non lo farebbe inserire: è un Set
set.add(new Persona("Sartori", "Fabio", "[email protected]"));
//Lo inserisce
set.add(new Persona("Fiamberti", "Francesco", "[email protected]"));
System.out.println("Set nuovo: ");
i = set.iterator();
while(i.hasNext())
System.out.println(i.next());
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
Output:
Persona [cognome=Tisato, nome=Francesco]
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Sartori, nome=Fabio]
Persona [cognome=Micucci, nome=Daniela]
Set nuovo: Persona [cognome=Tisato, nome=Francesco]
Persona [cognome=Fiamberti, nome=Francesco]
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Sartori, nome=Fabio]
Persona [cognome=Micucci, nome=Daniela]
56
28
6/3/2014
Interface Map: Esempio TreeMap
import
import
import
import
java.util.Collection;
java.util.Iterator;
java.util.Map;
java.util.TreeMap;
public class DemoPersonaTreeMap {
public static void main(String a[]){
Map<Persona, String> map = new TreeMap<Persona, String>();
map.put(new Persona("Micucci", "Daniela", "[email protected]"), "Docente - Turno B");
map.put(new Persona("Denaro", "Giovanni", "[email protected]"), "Esercitatore - Turno B");
map.put(new Persona("Tisato", "Francesco", "[email protected]"), "Docente - Turno A");
map.put(new Persona("Sartori", "Fabio", "[email protected]"), "Esercitatore - Turno B");
Collection<String> values = map.values();
Iterator<String> i = values.iterator();
System.out.println("Valori:");
while(i.hasNext())
System.out.println(i.next());
Collection<Persona> keys = map.keySet();
Iterator<Persona> ii = keys.iterator();
System.out.println("Chiavi:");
while(ii.hasNext())
System.out.println(ii.next());
//Chiave già presente! Da specifica del metodo put,
//sostituisce il vecchio valore con il nuovo
map.put(new Persona("Sartori", "Fabio",
"[email protected]"), "Esercitatore - Turno B");
map.put(new Persona("Fiamberti", "Francesco",
"[email protected]"), "Tutor - Turno B");
ii = keys.iterator();
System.out.println("Chiavi:");
while(ii.hasNext())
System.out.println(ii.next());
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
Chiavi ordinate
Chiavi duplicate non presenti
Output:
Valori:
Esercitatore ‐ Turno B
Docente ‐ Turno B
Esercitatore ‐ Turno B
Docente ‐ Turno A
Chiavi:
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Micucci, nome=Daniela]
Persona [cognome=Sartori, nome=Fabio]
Persona [cognome=Tisato, nome=Francesco]
Chiavi:
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Fiamberti, nome=Francesco]
Persona [cognome=Micucci, nome=Daniela]
Persona [cognome=Sartori, nome=Fabio]
57
Persona [cognome=Tisato, nome=Francesco]
Interface Map: Esempio HashMap
import
import
import
import
java.util.Collection;
java.util.Iterator;
java.util.Map;
java.util.HashMap;
public class DemoPersonaHashMap {
public static void main(String a[]){
Map<Persona, String> map = new HashMap<Persona, String>();
map.put(new Persona("Micucci", "Daniela", "[email protected]"), "Docente - Turno B");
map.put(new Persona("Denaro", "Giovanni", "[email protected]"), "Esercitatore - Turno B");
map.put(new Persona("Tisato", "Francesco", "[email protected]"), "Docente - Turno A");
map.put(new Persona("Sartori", "Fabio", "[email protected]"), "Esercitatore - Turno B");
Collection<String> values = map.values();
Iterator<String> i = values.iterator();
System.out.println("Valori:");
while(i.hasNext())
System.out.println(i.next());
Collection<Persona> keys = map.keySet();
Iterator<Persona> ii = keys.iterator();
System.out.println("Chiavi:");
while(ii.hasNext())
System.out.println(ii.next());
//Chiave già presente! Da specifica del metodo put,
//sostituisce il vecchio valore con il nuovo
map.put(new Persona("Sartori", "Fabio",
"[email protected]"), "Esercitatore - Turno C");
map.put(new Persona("Fiamberti", "Francesco",
"[email protected]"), "Tutor - Turno B");
i = values.iterator();
System.out.println(“Valori:");
while(i.hasNext())
System.out.println(i.next());
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
Chiavi non ordinati
Chiavi duplicate non presenti
Output:
Valori:
Docente ‐ Turno A
Esercitatore ‐ Turno B
Esercitatore ‐ Turno B
Docente ‐ Turno B
Chiavi:
Persona [cognome=Tisato, nome=Francesco]
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Sartori, nome=Fabio]
Persona [cognome=Micucci, nome=Daniela]
Valori:
Docente ‐ Turno A
Tutor ‐ Turno B
Esercitatore ‐ Turno B
Esercitatore ‐ Turno C
58
Docente ‐ Turno B
29
6/3/2014
CLASSE COLLECTIONS
Programmazione con Java: Collection Framework
59
Classe Collections
• Collections è una classe che contiene metodi di utilità
• Esempi:
– sort(List)
• Ordina una lista con un algoritmo veloce, che evita di riordinare elementi uguali
– shuffle(List)
• Scambia gli elementi di una lista in ordine casuale
– reverse(List)
• Inverte l’ordine degli elementi di una lista
– fill(List, Object)
• Sovrascrive ogni elemento della lista con l’oggetto specificato
– copy(List dest, List src)
• Copia la lista sorgente in quella di destinazione
– binarySearch(List, Object)
• Cerca un elemento in una lista ordinata usando un algoritmo di ricerca binaria
• Nota: è possibile usare i metodi della classe Collections con qualsiasi classi di oggetti per cui sia stata definita una relazione d’ordine naturale tramite l’implementazione dell’interfaccia Comparable
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
60
30
6/3/2014
Esempio di utilizzo: sort
import
import
import
import
java.util.ArrayList;
java.util.Collections;
java.util.Iterator;
java.util.List;
public class DemoPersonaArrayList {
public static void main(String a[]){
List<Persona> lista = new ArrayList<Persona>();
lista.add(new Persona("Micucci", "Daniela", "[email protected]"));
lista.add(new Persona("Denaro", "Giovanni", "[email protected]"));
lista.add(new Persona("Tisato", "Francesco", "[email protected]"));
lista.add(new Persona("Sartori", "Fabio", "[email protected]"));
Iterator<Persona> i = lista.iterator();
while(i.hasNext())
System.out.println(i.next());
Collections.sort(lista);
System.out.println("Set ordinato: ");
i = lista.iterator();
while(i.hasNext())
System.out.println(i.next());
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
Output:
Persona [cognome=Micucci, nome=Daniela]
Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Tisato, nome=Francesco]
Persona [cognome=Sartori, nome=Fabio]
Set ordinato: Persona [cognome=Denaro, nome=Giovanni]
Persona [cognome=Micucci, nome=Daniela]
Persona [cognome=Sartori, nome=Fabio]
Persona [cognome=Tisato, nome=Francesco]
61
31