Le Collezioni (Java Collections) Le Collezioni (Java Collections) Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Liste e insiemi Lista (sequenza) Insieme Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Il framework Collection Le collection di Java rappresentano n’architettura nificata preposta all’uso e al trattamento di gruppi di oggetti. Consistono di: Interfacce: tipi di dati astratti che rappresentano collezioni, come List, Queue, Set e Map Implementazioni astratte: parziali implemetazioni di interfacce facilmente riadattabili Implementazioni concrete: classi basilari che implementano le interfacce fondamentali Algoritmi: implementazioni di funzioni basilari come ordinamento e ricerca, applicabili a tutte le collezioni Utilità: funzioni basilari applicate ad array di primitivi e riferimento Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe La gerarchia delle interfacce Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe L’interfaccia Collection public interface Collection<E> extends Iterable<E> { // Opera i int size(); boolean isEmpty(); boolean contains(Object element); boolean add(E element); // boolean remove(Object element); / / Iterator iterator(); // Optional Optional Opera boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean removeAll(Collection<?> c); boolean retainAll(Collection<?> c); void clear(); / / O p t i o n a l // Opera Object[] toArray(); <T> T[] toArray(T[] a); } // Optional // Optional // Optional Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Contratto del metodo add(E o) - opzionale ... Returns true if this collection changed as a result of the call. (Returns false if this collection does not permit duplicates and already contains the specified element.) ... limitations on what elements may be added to this collection. In particular, some collections will refuse to add null elements, and others will impose restrictions on the type of elements that may be added. Collection classes should clearly specify in their documentation any restrictions on what elements may be added. If a collection refuses to add a particular element for any reason other than that it already contains the element, it must throw an exception (rather than returning false)... Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Le interfacce di Collection Collection è la radice della gerarchia delle collection. Rappresenta gruppi di oggetti (elementi) che possono essere duplicati oppure no. Alcune possono essere ordinate altre no. Esistono implementazioni concrete di sottointerfacce quali List e Set List cattura il concetto di lista ordinata (o sequenza): gruppo di elementi posti in un qualche ordine. Implementazioni: ArrayList, LinkedList e Vector Set cattura il concetto di insieme: gruppo di elementi che non contiene duplicati (non contiene e1 e e2 se e1.equals(e2) . Implementazioni: HashSet Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Gerarchia (parziale) di Collection (List e Set) Collection List ArrayList LinkedList Set HashSet ! List! public void add(int index, E element)! Inserts!the!specified!element!at!the!specified!posi2on!in!this!list!(op2onal!opera2on).!! Shi7s!the!element!currently!at!that!posi2on!(if!any)!and!any!subsequent!elements!to!the! right!(adds!one!to!their!indices).! public E get(int index)! Returns!the!element!at!the!specified!posi2on!in!this!list.! public int indexOf(Object o) [lastIndexOf(Object o)]! Returns!the!index!of!the!first![last]!occurrence!of!the!specified!element!in!this!list,!or!C1!if! this!list!does!not!contain!the!element.! public E remove(int index)! Removes!the!element!at!the!specified!posi2on!in!this!list!(op2onal!opera2on).!!Shi7s!any! subsequent!elements!to!the!le7!(subtracts!one!from!their!indices).!!Returns!the!element! that!was!removed!from!the!list.! Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Esempio class Gatto { // costruttore public Gatto(int i) // restituisce l’ identificativo unico public int getID() } public class Cane { // costruttore public Cane(int i) // restituisce l’ identificativo public int getID() } unico Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Le Collezioni (Java Collections) Esempio: uso di non-generici import java.util.*; public class CaniEGatti { public static void main(String[] args) { /* definizione tipica : riferimento piu ’ uso del astratto */ List gatti = new ArrayList(); for(int i = 0; i < 7; i++) gatti.add(new Gatto(i)); /* nessun oggetti problema di tipo ad aggiungere diverso for (int i = 0; i < 3; i++) gatti.add(new Cane(i)); } } */ Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Svantaggi Uno svantaggio tipico è la perdita di informazione sul tipo quando si inseriscono oggetti nel contenitore. Infatti: poiché non vi sono restrizioni sul tipo di oggetti inseribili nel contenitore, è possibile inserire senza problemi cani in una collezione di gatti (fonte di potenziali errori) a causa della perdita del tipo, occorre eseguire una forzatura (cast) “corretta”, a run time, all’atto dell’estrazione dell’oggetto per non incorrere in un’eccezione Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Le Collezioni (Java Collections) Esempio import java.util.*; public class CaniEGatti { public static void main(String[] args) { List gatti = new ArrayList(); for(int i = 0; i < 7; i++) gatti.add(new Gatto(i)); gatti.add(new Cane(7)); /* Eccezione rilevata a run time */ for(int i = 0; i < gatti.size(); i++) ((Gatto)gatti.get(i)).id(); } } Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Parametrizzare la lista Per ovviare ai problemi precedenti è lecito definire una nuova classe lista parametrizzat List<Gatto> gatti = new ArrayList<Gatto>(); List<Cane> cani = new ArrayList<Cane>(); for (int i = 0; i < 7; i++) gatti.add(new Gatto(i)); // aggiungi for (int i = 0; i < 3; i++) cani.add(new Cane(i)); // aggiungi for (Gatto g : gatti) out.println(g); for (Cane c : cani) out.println(c); // estrai Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Vantaggi nell’uso di generici I principali vantaggi dovuti all’introduzione dei tipi generici sono: Il compilatore può verificare qulasiasi operazione add di oggetti alla collezione il tipo dell’oggetto estratto da una collezione è noto, quindi non vi è la necessità di operare un cast a un tipo diverso (fonte di potenziali errori se il cast è fatto su tipi non omologhi) Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe ArrayList vs LinkedList ArrayList ottimizzato l’accesso casuale (basato su array), non ottimizzati l’inserimento e l’eliminazione all’interno della lista (grosso modo equivalente a Vector) LinkedList ottimizzato l’accesso sequenziale, l’inserimento e l’eliminazione, indicato per implementare pile (LIFO) e code (FIFO), infatti contiene i metodi: addFirst(), addLast(), getFirst(), getLast(), removeFirst( ), removeLast() ! Collections! MeHe!a!disposizione!metodi!per!effeHuare! operazioni!generiche!con!le!Collezioni.! • • • • • Ordinare!una!lista!(sort)! Mescolare!una!lista!(shuffle)! Scambiare!elemen2!di!una!lista!(swap)! Copiare!una!lista!(copy)! …! Ne!esiste!una!equivalente!anche!per!gli! array!(Arrays).! ! Collections! Esempio:!metodi!sort! ! static void sort(List<T> list)! Sorts!the!specified!list!into!ascending!order,!according!to!the! natural'ordering!of!its!elements.! !! static void sort(List<T> list, Comparator<? super T> c) ! Sorts!the!specified!list!according!to!the!order!induced!by!the! !! specified!comparator. ! Collections! Esempio:!metodo!sort! Ordiniamo!una!lista!di!Integer!secondo!l’ordine! naturale.! List<Integer> listaInteri = new ArrayList<Integer>();! listaInteri.add(5);! listaInteri.add(2);! listaInteri.add(9);! Collections.sort(listaInteri);! System.out.println("Lista di interi ordinata: ");! for (int i:listaInteri) {! System.out.println(i);! } !! Comparable! ! Per!definire!l’ordinamento!naturale!di!una!classe,!la!classe!deve! implementare!l’interfaccia!Comparable.! E’#buona#norma#che#il#metodo#compareTo#sia#simmetrico#e# consistente#con#equals!# # java.u7l#Interface#Comparable<T># T!C!the!type!of!objects!that!this!object!may!be!compared!to! ! int!compareTo(T#o)! Compares!this!object!with!the!specified!object!for!order.!Returns!a! nega2ve!integer,!zero,!or!a!posi2ve!integer!as!this!object!is!less!than,! equal!to,!or!greater!than!the!specified!object.! ! Un!comparatore!implementa!un!metodo!compare!per! comparare!due!oggeV!secondo!un!ordine!totale.!Puo’!essere! usato!come!secondo!argomento!del!metodo! Collections.sort.! E’#buona#norma#che#il#metodo#compare#sia#simmetrico#e# consistente#con#equals!# # java.util Interface Comparator<T>! T!C!the!type!of!objects!that!may!be!compared!by!this!comparator! ! int compare(T o1, T o2)! Compares!its!two!arguments!for!order.!Returns!a!nega2ve!integer,!zero,! or!a!posi2ve!integer!as!the!first!argument!is!less!than,!equal!to,!or! greater!than!the!second.! ! ! Esempio:!GaHo!comparabile! ! public class Gatto implements Comparable<Gatto> {! // ....! @Override! public int compareTo(Gatto gatto) {! if (gatto.getID() == getID()) {! return 0;! } else if (gatto.getID() < getID()) {! return -1;! } else {! return 1;! }! }! } !! ! ! Esempio:!GaHo!comparabile! Creiamo#un#comparatore#che#ordini#i#gaB#in#base#al#nome.! ! public class NomeGattoComparator implements Comparator<Gatto> {! ! @Override! public int compare(Gatto g1, Gatto g2) {! return g1.getNome().compareTo(g2.getNome());! }! } !! ! sort! Esempio:!ordinamento!di!gaV!in!base!al!nome! ! List<Gatto> gatti = new ArrayList<Gatto>();! gatti.add(new Gatto(1, "Tom"));! gatti.add(new Gatto(1, "Felix"));! gatti.add(new Gatto(1, ”Star"));! ! System.out.println("Lista gatti:");! for (Gatto gatto:gatti) {! System.out.println(gatto.getNome());! }! Collections.sort(gatti, new NomeGattoComparator());! System.out.println("Lista gatti ordinata:");! for (Gatto gatto:gatti) {! System.out.println(gatto.getNome());! }! Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Scansione: for-each e Iteratori Il costrutto for-each: for (Object o : collection) System.out.println(o); L’interfaccia Iterator: public interface Iterator<E> { boolean hasNext(); E next(); void remove(); } Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Uso: for-each e Iteratori Si usa l’iteratore for-each quando: si deve rimuovere il corrente oggetto (esempio filtraggio) static void filter(Collection c) { for (Iterator i = c.iterator(); i.hasNext();) { if (!cond(i.next())) i.remove(); } si deve rimpiazzare un elemento nella lista o nell’array durante l’attraversamento ListIterator<E> extends Iterator<E> occorre iterare su molteplici collezioni simultaneamente Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Uso di Iterator Problema Usare Iterator per modificare la classe CaniEGatti al fine di eliminare dalla lista gatti i gatti con ID dispari e dalla lista cani i cani con ID pari Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Codifica List<Gatto> gatti = new ArrayList<Gatto>(); List<Cane> cani = new ArrayList<Cane>(); for (int i = 0; i < 7; i++) gatti.add(new Gatto(i)); // aggiungi for (int i = 0; i < 3; i++) cani.add(new Cane(i)); // aggiungi // iterator for (Iterator<Gatto> eG = gatti.iterator(); eG.hasNext();){ if ((eG.next().getID() % 2) == 1) eG.remove(); } for (Iterator<Cane> eC = cani.iterator(); eC.hasNext();) { if ((eC.next().getID() % 2) == 0) eC.remove(); } Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Indice 1 Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di Liste Scansione: for-each e Iteratori Esempi di insiemi Mappe Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe L’interfaccia Set public interface Set<E> extends Collection<E> { // Operazioni base int size(); boolean isEmpty(); boolean contains(Object element); boolean add(E element); // boolean remove(Object element); / / Iterator iterator(); // Optional Optional O p e r a z i o n i su c o l l e z i o n i boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean removeAll(Collection<?> c); boolean retainAll(Collection<?> c); void clear(); // Opera i Object[] toArray(); <T> T[] toArray(T[] a); // Optional // Optional // Optional // Optional Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe La classe HashSet Una della classi più utili nella gestione di insieme di oggetti è la classe HashSet Set<T> insieme = new HashSet<T>(c); Osservazione: Notare che si usa il tipo interfaccia Set per la variabile insieme (pratica fortemente raccomadata). Si produce codice molto flessibile. Per esempio, per avere l’elenco ordinato: Set<T> insieme = new TreeSet<T>(c); Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Il codice hash associato agli oggetti Funzione hash Un funzione hash in Java è una funzione che mappa un oggetto in un numero intero (codice hash) Proprietà: oggetti logicamente uguali devono avere lo stesso codice hash Oggetti distinti possono avere lo stesso codice hash (collisione), l’importante è che questo fatto sia piuttosto infrequente Deve essere una funzione semplice e “veloce” da calcolare, possibilmente dipendente da campi della classe Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Il metodo hashCode() Contratto di Object.hashCode Il metodo hashCode deve produrre lo stesso numero anche quando invocato più volte sullo stesso oggetto. Se due oggetti sono uguali in accordo al metodo equal (Object o), allora il metodo hashCode invocato su entrambi gli oggetti deve produrre lo stesso numero. Non è richiesto che oggetti diversi producano codici hash distinti Osservazioni: normalmente questo contratto viene disatteso! Per usare HashSet è fondamentale osservarlo! Regola: si deve sovrascrivere hashCode() in tutte le classi ove viene sovrascritto equal (Object o) Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Esempi di codici hash ... System.out.println("cane".hashCode()); System.out.println("cane".hashCode()); System.out.println("gatto".hashCode()); Quadrato q = new Quadrato(1); System.out.println(q.hashCode()); q = new Quadrato(1); System.out.println(q.hashCode()); q = new Quadrato(2); System.out.println(q.hashCode()); Persona p = new Persona("Paolo","Rossi"); System.out.println(p.hashCode()); p = new Persona("Paolo","Rossi"); System.out.println(p.hashCode()); p = new Persona("Paola","Rossi"); System.out.println(p.hashCode()); ... Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Stampa dei Risultati Esecuzione del metodo main della classe HashCodeEx: HashCode HashCode HashCode HashCode HashCode HashCode HashCode HashCode HashCode di: di: di: di: di: di: di: di: di: "cane" -> 3046037 "cane" -> 3046037 "gatto" -> 98127573 Quadrato(1) -> 19972507 Quadrato(1) -> 7754385 Quadrato(2) -> 2548785 Persona("Paolo","Rossi") Persona("Paolo","Rossi") Persona("Paola","Rossi") //non definito //non definito //non definito -> -1832489941 -> -1832489941 -> -1832490375 Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Uso di HashSet Problema Usare la classe HashSet (TreeSet) per trovare le parole duplicate in una stringa passata come argomento sulla linea di comando >java TrovaDuplicati ciao mamma ciao Duplicati: ciao 2 parole distinte: [mamma, ciao] Duplicati: ciao 2 parole distinte (ordinate): [ciao, mamma] Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Esempio import java.util.*; class TrovaDuplicati { public static void main(String args[]) { Set<String> s = new HashSet<String>(); for (String a : args) if (!s.add(a)) System.out.println("Duplicati: " + a); System.out.println(s.size() + " parole distinte: " + s); s = new TreeSet<String>(); for (String a : args) if (!s.add(a)) System.out.println("Duplicati: " + a); System.out.println(s.size() + " parole distinte (ordinate): " + s) } } Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Indice 1 Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di Liste Scansione: for-each e Iteratori Esempi di insiemi Mappe Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe L’interfaccia Mappa public interface Map<K,V> { // Opera ion V put(K key, V value); V get(Object key); V remove(Object key); boolean containsKey(Object key); boolean containsValue(Object value); int size(); boolean isEmpty(); // Opera ion void putAll(Map<? extends K,? extends V> t); void clear(); // Collezioni public Set<K> keySet(); public Collection<V> values(); public Set<Map.Entry<K,V>> entrySet(); Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Mappe Map Un gruppo di coppie di oggetti chiave-valore. Una Map può resti uire un Set di chiavi, una Collection di valori o un Set delle sue coppie. Idea: associare oggetti (chiave) a oggetti (valore), invece di associare numeri a oggetti (come ArrayList) Map HashMap Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Uso di HashMap Problema Usare la classe HashMap (TreeMap) per calcolare le occorrenze di ogni singola parola st passat argomento sulla linea di comando >java FrequenzaParole ciao mamma ciao 2 parole distinte: {mamma=1, ciao=2} 2 parole distinte (ordinate): {ciao=2, mamma=1} Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Esempio public class FrequenzaParole { public static void main(String args[]) { Map<String, Integer> m = new HashMap<String, Integer>(); for (String a : args) { Integer freq = m.get(a); m.put(a, (freq == null ? 1 : freq + 1)); } System.out.println(m.size() + " parole distinte:"); System.out.println(m); m = new TreeMap<String, Integer>(); for (String a : args) { Integer freq = m.get(a); m.put(a, (freq == null ? 1 : freq + 1)); } System.out.println(m.size() + " parole distinte:"); System.out.println(m); } } Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Problema Problema Scrivere un programma che mostri la pseudo casualità del generatore di numeri casuali implementato nella classe java.util.Random utilizzando la classe Contatore per contare le occorrenze dei numeri. Metodo: genero molti (10000) numeri nell’intervallo [1, 10] e mostro la frequenza con cui si manifestano, quindi stampo la coppia (numero, frequenza) Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Risultato >java DistUniformeDemo Frequenze di 10000 numeri (tra 1 e 10) generati a caso: [1=974, 2=1000, 3=954, 4=1010, 5=993, 6=1049, 7=996, 8=1000, 9=977, 10=1037] Le Collezioni (Java Collections) Modellare liste e insiemi Esempi di liste Scansione Esempi di insiemi Mappe Problema con mappe ordinate per chiave Problema Scrivere un programma che gestisca una rubrica telefonica: una chiave (ordinabile), per es. cognome e un valore per es. Persona. Si consiglia l’uso di java.util.TreeMap