Programmazione Parametrica ( a.k.a. Generics ). Introduzione ai meccanismi e concetti della programmazione parametrica Generics e relationi di sottotipo.

Slides:



Advertisements
Presentazioni simili
I numeri, l’ora, I giorni della settimana
Advertisements

Cache Memory Prof. G. Nicosia University of Catania
Dipartimento di Ingegneria Idraulica e Ambientale - Universita di Pavia 1 Caduta non guidata di un corpo rettangolare in un serbatoio Velocità e rotazione.
Teoria e Tecniche del Riconoscimento
1 MeDeC - Centro Demoscopico Metropolitano Provincia di Bologna - per Valutazione su alcuni servizi erogati nel.
TAV.1 Foto n.1 Foto n.2 SCALINATA DI ACCESSO ALL’EREMO DI SANTA CATERINA DEL SASSO DALLA CORTE DELLE CASCINE DEL QUIQUIO Foto n.3 Foto n.4.
1 Le s-espressioni. 2 Un nuovo esempio completo: le s-espressioni Sexpr 4 alberi binari (possibilmente vuoti) che hanno sulle foglie atomi (stringhe)
1 Progettazione gerarchica delle s- espressioni, utilizzando lereditarietà
1 Pregnana Milanese Assessorato alle Risorse Economiche Bilancio Preventivo P R O P O S T A.
Interfacce Java.
Sequential Statements. – Il VHDL simula lo svolgersi in parallelo di varie operazioni – Loggetto fondamentale e il PROCESS – Un PROCESS contiene una serie.
Frontespizio Economia Monetaria Anno Accademico
Un DataBase Management System (DBMS) relazionale client/server.
Programmazione Parametrica ( a.k.a. Generics )
Programmazione Parametrica ( a.k.a. Generics ). Introduzione ai meccanismi e concetti della programmazione parametrica Generics e relationi di sottotipo.
XXIV Congresso ACOI 2005 Montecatini Terme Maggio 2005
Virtual CPU - Eniac Dr.ssa Veronica Marchetti
Esempio: Tombola! Parte seconda.
Unified Modeling Language class C {…} class B extends C {…} Esiste una notazione grafica per mostrare le relazioni di ereditarietà. Object StringC B Tutte.
Sezione: Costruttori Costruttori. Definizione dei costruttori Se per una classe A non scrivo nessun costruttore, il sistema automaticamente crea il costruttore.
prompt> java SumAverage
1 struct Pila { private: int size; int defaultGrowthSize; int marker; int * contenuto; void cresci(int increment); public: Pila(int initialSize) ; Pila();
HDM Information Design notation v.4. HDM Information Design.
Programmazione 1 9CFU – TANTE ore
Biometry to enhance smart card security (MOC using TOC protocol)
Costruzione di Interfacce Lezione 10 Dal Java al C++ parte 1
Canale A. Prof.Ciapetti AA2003/04
TIPOLOGIA DELLE VARIABILI SPERIMENTALI: Variabili nominali Variabili quantali Variabili semi-quantitative Variabili quantitative.
Ufficio Studi UNIONCAMERE TOSCANA 1 Presentazione di Riccardo Perugi Ufficio Studi UNIONCAMERE TOSCANA Firenze, 19 dicembre 2000.
1 Ultima Lezione del Corso di Fondamenti di Informatica 1 a.a – 06 Ma 29-Nov-2005.
1. Conoscere luso delle collezioni in Java Comprendere le principali caratteristiche nelle varie classi di Collection disponibili Saper individuare quali.
JAVA C import java.util.*; #include <stdio.h>
2000 Prentice Hall, Inc. All rights reserved. 1 Capitolo 3 - Functions Outline 3.1Introduction 3.2Program Components in C++ 3.3Math Library Functions 3.4Functions.
6.6Ordinamento di Vettori Ordinamento di dati –Applicazione computazionale importante –Virtualmente ogni organizzazione deve ordinare dei dati Enormi quantità
MP/RU 1 Dicembre 2011 ALLEGATO TECNICO Evoluzioni organizzative: organico a tendere - ricollocazioni - Orari TSC.
Capitolo OD.
2000 Prentice Hall, Inc. All rights reserved. 1 Capitolo 6: Classi e astrazione dati 1.Introduzione 2.Definizione delle strutture 3.Accedere ai membri.
Sottoprogrammi e Unità di Compilazione Nicola Fanizzi Laboratorio - Corso di Programmazione (B) C.d.L. in Informatica DIB - Università degli Studi di Bari.
1 laboratorio di calcolo II AA 2003/04 ottava settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza tel. ( )
Progetto di applicazioni grafiche. Disegno di forme complesse Prassi : un classe per ciascuna forma Progetta la forma individuando le componenti base.
CALCIO SKY 2007 – 2008 PROFILO DI ASCOLTO. 2 INDICE DEGLI ARGOMENTI Profilo di ascolto CALCIO SERIE A 2007 – 2008 Totale campionato (tutte le partite)……………………………………………….
Le regole Giocatori: da 2 a 10, anche a coppie o a squadre Scopo del gioco: scartare tutte le carte per primi Si gioca con 108 carte: 18 carte.
Players: 3 to 10, or teams. Aim of the game: find a name, starting with a specific letter, for each category. You need: internet connection laptop.
Compito desame del Svolgimento della Sezione 5: CONTROLLORI Esempio preparato da Michele MICCIO.
Java Collections.
Elementi di programmazione ad oggetti a. a. 2009/2010 Corso di Laurea Magistrale in Ingegneria Elettronica Docente: Mauro Mazzieri, Dipartimento di Ingegneria.
Palermo, may 2010 F.Doumaz, S.Vinci (INGV-CNT- Gruppo di telerilevamento)
La Cooperativa Sociale Le Sagome nasce nel dicembre 2005, grazie ad un progetto finanziato in parte dal fondo sociale europeo, coordinato e guidato da.
1 Negozi Nuove idee realizzate per. 2 Negozi 3 4.
ORDINE DI CHIAMATA a 1minuto e 2 minuti PRINCIPALI TEMPI DELLA COMPETIZIONE ORDINE DI CHIAMATA a 1minuto e 2 minuti PRINCIPALI TEMPI DELLA COMPETIZIONE.
24 aprile 2002 Avvisi: Risultati 1 o Esonero: (entro) lunedi 27 disponibili nella pag. WEB, ma anche esposti nella bacheca fuori dal corridoio 2 o dente,
/ Elementi di C++ Introduzione a ROOT , Laboratorio Informatico ROOT warm up , Laboratorio Informatico Introduzione a.
Multiset. Progettare (specifica con identificazione delle eventuali astrazioni necessarie, incluse eccezioni, e implementazione) del tipo di dato Multiset,
21 marzo 2002 (ri-)Avvisi: Giovedi 28 marzo la lezione e sospesa. Nuovo indirizzo di Spedire messaggi e esercizi solo.
Funzioni stringhe. chr Restituisce il carattere di un valore ascii dato. Per vedere lelenco dei codici ascii clicca QQQQ uuuu iiiiEsempio
Test con JUnit. zJUnit è un ambiente di test per programmi Java ySviluppato da Kent Beck É possibile usare JUnit allinterno di Eclipse per eseguire i.
1 Simulated multiple inheritance Sandro Pedrazzini Approfondimento Simulated multiple inheritance in Java.
Sviluppare un programma in C che, dato un array da 100 elementi interi caricato con numeri casuali compresi tra [10,100], sia in grado di cercare il valore.
1 Sky 2 Sky 3 Sky L’Universo Aperto La teoria del Big Bang prevede che, se la densità globale dell’universo non raggiunge un valore di Ωo (Omega Zero)
Collection & Generics in Java
Moles and Formula Mass.
Passato Prossimo. What is it?  Passato Prossimo is a past tense and it is equivalent to our:  “ed” as in she studied  Or “has” + “ed” as in she has.
Italian 1 -- Capitolo 2 -- Strutture
1 Acceleratori e Reattori Nucleari Saverio Altieri Dipartimento di Fisica Università degli Studi - Pavia
Customer satisfaction anno 2013 Ospedale di Circolo Fondazione Macchi Varese Presentazione risultati (Febbraio 2014)
DIRETTIVI UNITARI SPI-CGI – FNP-CISL - UILP-UIL TERRITORIO LODIGIANO Lunedì 23 marzo 2015 dalle ore 9,00 alle ore 13,00 Presso la sala Conferenze Confartigianato.
ANNI POLIZZA 1 IMPORTO PREMIO UNICO INTERESSE NETTO ANNUO (%) TOTALE INTERESSI (€) POLIZZA 2 IMPORTO PREMIO ANNUO (INDICIZZATO) POLIZZA 3 IMPORTO PREMIO.
Fondamenti di informatica Oggetti e Java Luca Cabibbo Luca Cabibbo – Fondamenti di informatica: Oggetti e Java Copyright © 2004 – The McGraw-Hill Companies.
IL GIOCO DEL PORTIERE CASISTICA. Caso n. 1 Il portiere nella seguente azione NON commette infrazioni.
Transcript della presentazione:

Programmazione Parametrica ( a.k.a. Generics )

Introduzione ai meccanismi e concetti della programmazione parametrica Generics e relationi di sottotipo wildcards generics e vincoli Implemendaizone di classi e metodi parametrici Supporto per i generics nella JVM

Programmazione polimorfa Polimorfo ~ multiforme, di molti tipi Programmazione polimorfa: creazione di costrutti (classi e metodi) che possono essere utilizzati in modo uniforme su dati di tipo diverso In Java, tradizionalmente ottenuta mediante i meccanismi di sottotipo ed ereditarietà Da Java 1.5. mediante i meccanismi di parametrizzazione di tipo (a.k.a. generics)

Variabili di Tipo Le variabili (o parametri) di tipo pemettono di creare astrazioni di tipo Classico caso di utilzzo nelle classi Container E = variabile di tipo astrae (e rappresenta) il tipo delle componenti public class ArrayList { public ArrayList() {... } public void add(E element) {... }... } Continua

Variabili di Tipo Possono essere istanziate con tipi classe o interfaccia Vincolo: tipi che istanziano variabili di tipo non possono essere primitivi (devono essere tipi riferimento) Classi wrapper utili allo scopo ArrayList ArrayList ArrayList // No! ArrayList

Variabili di tipo e controlli di tipo Utilizzare variabili di tipo nella programmazione permette maggiori controlli sulla correttezza dei tipi in fase di compilazione Aumenta quindi la solidità e robustezza del codice Continua

Variabili di tipo e controlli di tipo Un classico caso di utilizzo di containers Il cast è problematico, per vari motivi verboso, fonte di errori a run time Ma necessario per la compilazione e per localizzare leventuale errore a run time Continua List intList = new LinkedList(); intList.add(new Integer(0)); Integer x = (Integer) intList.iterator().next();

Variabili di tipo e controlli di tipo Container generici: più sintetici ed eleganti Compilatore può stabilire un invariante sugli elementi della lista garantire lassenza di errori a run-time in forza di quellinvariante. List intList = new LinkedList (); intList.add(new Integer(0)); Integer x = intList.iterator().next(); Continua

Variabili di tipo e controlli di tipo Ora non è possibile aggiungere una stringa ad intlist:List Le variabili di tipo rendono il codice parametrico più robusto e semplice da leggere e manutenere List intList = new LinkedList (); intList.add(new Integer(0)); Integer x = intList.iterator().next();

Classi parametriche: definizione // nulla di particolare, a parte i parametri // tra parentesi angolate public interface List { void add(E x); Iterator iterator(); } public interface Iterator { E next(); boolean hasNext(); } Un frammento delle interfacce List e Iterator nel package java.util.*

Classi parametriche: uso Quando utilizziamo un tipo parametrico, tutte le occorrenze dei parametri formali sono rimpiazzate dallargomento (parametro attuale) Meccanismo simile a quello del passaggio dei parametri in un metodo Diversi usi generano tipi diversi Ma... classi parametriche compilate una sola volta danno luogo ad un unico file.class

Sintassi: uso GenericClassName Esempio: ArrayList HashMap Scopo: Fornire tipo specifici per ciascuna delle variabili di tipo introdotte nella dichiarazione

public class Pair { public Pair(T firstElement, S secondElement) { first = firstElement; second = secondElement; } public T getFirst() { return first; } public S getSecond() { return second; } private T first; private S second; } Esempio: Pair Una semplice classe parametrica per rappresentare coppie di oggetti Continua

Esempio: Pair Una semplice classe parametrica per rappresentare coppie di oggetti: I metodi getFirst e getSecond restituiscono il primo e secondo elemento, con i tipi corrispondenti Pair result = new Pair ("Harry Hacker", harrysChecking); String name = result.getFirst(); BankAccount account = result.getSecond();

Variabili di tipo: convenzioni VariabileSignificato Inteso ETipo degli elementi in una collezione KTipo delle chiavi in una mappa VTipo dei valori in una mappa T,S,UTipi generici

Esempio: LinkedList public class LinkedList {... public E removeFirst() { if (first == null) throw new NoSuchElementException(); E element = first.data; first = first.next; return element; }... private Node first; private class Node { E data; Node next; } } Continua

Esempio: LinkedList private class Node { F data; Node next; } public class LinkedList {... public E removeFirst() { if (first == null) throw new NoSuchElementException(); E element = first.data; first = first.next; return element; }... private Node first; } Continua

Esempio: LinkedList Notiamo la struttura della classe ausiliaria che specifica la struttura dei nodi Se la classe è interna, come in questo caso, non serve alcun accorgimento allinterno di Node possiamo utilizzare il tipo E, il cui scope è tutta la classe Se invece la classe è esterna, dobbiamo renderla generica public class ListNode

File LinkedList.java 001: import java.util.NoSuchElementException; 002: 003: /** 004: A linked list is a sequence of nodes with efficient 005: element insertion and removal. This class 006: contains a subset of the methods of the standard 007: java.util.LinkedList class. 008: */ 009: public class LinkedList 010: { 011: /** 012: Constructs an empty linked list. 013: */ 014: public LinkedList() 015: { 016: first = null; 017: } 018: Continua

File LinkedList.java 019: /** 020: Returns the first element in the linked list. the first element in the linked list 022: */ 023: public E getFirst() 024: { 025: if (first == null) 026: throw new NoSuchElementException(); 027: return first.data; 028: } 029: 030: /** 031: Removes the first element in the linked list. the removed element 033: */ 034: public E removeFirst() 035: { Continua

File LinkedList.java 036: if (first == null) 037: throw new NoSuchElementException(); 038: E element = first.data; 039: first = first.next; 040: return element; 041: } 042: 043: /** 044: Adds an element to the front of the linked list. element the element to add 046: */ 047: public void addFirst(E element) 048: { 049: Node newNode = new Node(); 050: newNode.data = element; 051: newNode.next = first; 052: first = newNode; 053: } Continua

File LinkedList.java 054: 055: /** 056: Returns an iterator for iterating through this list. 057: 058: */ 059: public ListIterator listIterator() 060: { 061: return new LinkedListIterator(); 062: } 063: 064: private Node first; 065: 066: private class Node 067: { 068: E data; 069: Node next; 070: } 071: Continua

LinkedListIterator La definiamo come classe interna di LinkedList Implements linterfaccia ListIterator Ha accesso al campo first e alla classe interna Node

Classe LinkedListIterator 072: private class LinkedListIterator implements ListIterator 073: { 074: /** 075: Costruisce un iteratore posizionato sul primo 076: elemento della lista 077: */ 078: public LinkedListIterator() 079: { 080: last = null; // ultimo nodo visitato 081: previous = null; // precedente a position 082: } 083: Continua

LinkedListIterator – next() 084: /** 085: Posizione literatore sul prossimo. il prossimo elemento 087: */ 088: public E next() 089: { 090: if (!hasNext()) 091: throw new NoSuchElementException(); 092: previous = last; // Remember for remove 093: 094: if (last == null) 095: last = first; 096: else 097: last = last.next; 098: 099: return last.data; 100: } 101: 102: Continua

LinkedListIterator – hasNext() 102: /** 103: Testa se cè un elemento dopo lultimo 104: visitato. true se esiste un elemento dopo 106: lultimo visitato 107: */ 108: public boolean hasNext() 109: { 110: if (last == null) 111: return first != null; 112: else 113: return last.next != null; 114: } 115: 116: Continua

LinkedListIterator – add() 117: /** Aggiunge un elemento dopo last e sposta 118: literatore sul prossimo elemento. 119: */ 121: public void add(E element) 122: { 123: if (last == null) 124: { 125: addFirst(element); last = first; 127: } 128: else 129: { 130: Node newNode = new Node(); 131: newNode.data = element; 132: newNode.next = last.next;// (1) 133: last.next = newNode; // (2) 134: last = newNode; // (3) 135: } 136: previous = last; // (4) 137: } Continua

LinkedListIterator – add() last

LinkedListIterator – remove() 140: /** Rimuove lelemento puntato da last. Può essere 141: invocato solo dopo una chiamata a next() 142: */ 143: public void remove() 144: { 145: if (previous == last) 146: throw new IllegalStateException(); 147: 148: if (last == first) 149: { 150: removeFirst(); 151: } 152: else 153: { 154: previous.next = last.next; // (1) 155: } 156: last = previous; // (2) 157: } Continua

LinkedListIterator –remove() last

Classe LinkedListIterator 159: /** 160: Sets the last traversed element to a different 161: value. element the element to set 163: */ 164: public void set(E element) 165: { 166: if (position == null) 167: throw new NoSuchElementException(); 168: position.data = element; 169: } 170: 171: private Node position; 172: private Node previous; 173: } // end LinkedListIterator 174: } // end LinkedList

File ListIterator.java 01: /** 02: A list iterator allows access of a position in a linked 03: list. This interface contains a subset of the methods 04: of the standard java.util.ListIterator interface. The 05: methods for backward traversal are not included. 06: */ 07: public interface ListIterator 08: { 09: /** 10: Moves the iterator past the next element. the traversed element 12: */ 13: E next(); 14: 15: /** 16: Tests if there is an element after the iterator 17: position. Continua

File ListIterator.java true if there is an element after the iterator 19: position 20: */ 21: boolean hasNext(); 22: 23: /** 24: Adds an element before the iterator position 25: and moves the iterator past the inserted element. element the element to add 27: */ 28: void add(E element); 29: 30: /** 31: Removes the last traversed element. This method may 32: only be called after a call to the next() method. 33: */ Continua

File ListIterator.java 34: void remove(); 35: 36: /** 37: Sets the last traversed element to a different 38: value. element the element to set 40: */ 41: void set(E element); 42: }

Generics e sottotipi Consideriamo La prima istruzione è sicuramente legale, la seconda è più delicata … Number è una classe astratta che ha Integer, Double e altre classi wrapper come sottotipi Per capire se la seconda istruzione sia da accettare come legale continuiamo con lesempio … Continua List li = new ArrayList (); List ln = li;

Generics e sottotipi Come si vede abbiamo un problema nella terza istruzione inseriamo un Double (via auto- boxing, ricordate?) nella quarta estraiamo un Integer ! Il vero problema è nella seconda istruzione soluzione: errore di compilazione per lassegnamento al secondo Continua List li = new ArrayList (); List ln = li; ln.add(3.14); Integer i = li.get(0); // uh oh...

Generics e sottotipi In generale, dati due tipi A e B, ed tipo generico C abbiamo che: Quindi, per le stesse ragioni di prima Continua A B non implica C C Set non è sottotipo di Set

Generics e sottotipi Le limitazione sulle relazioni di sottotipo sono contro-intuitive uno degli aspetti più complessi dei generics Non solo … sono anche decisamente troppo restrittive illustriamo con un esempio Continua

Generics e sottotipi Un metodo che stampa gli elementi di una collezione Versione tradizionale Continua void printCollection(Collection c) { Iterator i = c.iterator(); for (k = 0; k < c.size(); k++) { System.out.println(i.next()); }

Generics e sottotipi Stampa degli elementi di una collezione Versione generics: primo tentativo utile solo per Collection non per qualsiasi collezione Collection non è il supertipo di tutte le collezioni Continua void printCollection(Collection c) { for (Object e:c) System.out.println(e); }

Wildcards Stampa degli elementi di una collezione Versione generics: secondo tentativo Collection è il supertipo di tutte le Collections la wildcard ? indica un qualche tipo, non specificato Continua void printCollection(Collection c) { for (Object e:c) System.out.println(e); }

Wildcards Possiamo estrarre gli elementi di c al tipo Object Corretto perché, qualunque sia il loro vero tipo, sicuramente è sottotipo di Object Continua void printCollection(Collection c) { for (Object e:c) System.out.println(e); }

Wildcards Continua Collection c = new ArrayList (); c.add(new String()); // errore di compilazione! Daltra parte … visto che non sappiamo esattamente quale tipo indica ?, non possiamo assegnare valori

Date un esempio di codice che causerebbe errore in esecuzione se permettessimo di aggiungere elementi a Collection Domanda

Lultima istruzione invocherebbe intValue() sul primo elemento di ci ma quellelemento ha tipo String … In realtà il compilatore anticipa lerrore, segnalando il problema sulla add() Risposta Collection ci = new ArrayList ; Colletion c = ci; c.add(a string); ci.get(0).intValue();

Wilcards con vincoli ( bounded ) Shapes : un esempio classico public abstract class Shape { public abstract void draw(Graphics g); } public class Circle extends Shape { private int x, y, radius; public void draw(Graphics g) {... } } public class Rectangle extends Shape { private int x, y, width, height; public void draw(Graphics g) {... } } Continua

Wilcards con vincoli ( bounded ) Graphics e il metodo draw() Solito problema: drawAll() non può essere invocato su una List public class Graphics { // disegna una shape public void draw(Shape s) { s.draw(this); } // disegna tutte le shapes di una lista public void drawAll(List shapes) { for (Shape s:shapes) s.draw(this) }... } Continua

Bounded Wilcards Quello che ci serve è un metodo che accetti liste di qualunque (sotto) tipo di Shape List bounded wildcard indica un tipo sconosciuto, sottotipo di Shape il bound può essere qualunque tipo riferimento (classe o interfaccia) Ora il metodo ha la flessibilità necessaria e desiderata void drawAll(List shapes) {... } Continua

Bounded Wilcards Graphics e il metodo draw() public class Graphics { // disegna una shape public void draw(Shape s) { s.draw(this); } // disegna tutte le shapes di una lista public void drawAll(List shapes) { for (Shape s:shapes) s.draw(this) }... } Continua

Bounded Wilcards Daltra parte, cè sempre un prezzo da pagare Il solito vincolo … Non possiamo modificare strutture con questi tipi [ perché? ] void addRectangle(List shapes) { // errore di compilazione shapes.add(new Rectangle()); }

Metodi che dipendono da una variabile di tipo Possono essere definiti allinterno di qualunque classe, generica o meno N.B. Evitiamo List perché List renderebbe il metodo poco utile (non utilizzabie su liste arbitrarie) /* trasforma un array in una lista, copiando * tutti gli elementi di a in l */ static void array2List(Object[] a, List l){... } Metodi Generici Continua

Metodi Generici Al solito però non possiamo aggiungere elementi ad una struttura (o modificare) con elementi di tipo wildcard /* trasforma un array in una lista, copiando * tutti gli elementi di a in l */ static void array2List(Object[] a, List l) { for (Object o : a) l.add(o) // compiler error } Continua

Metodi Generici Soluzione: rendiamo il metodo parametrico possiamo invocare questo metodo con una qualunque lista il cui tipo sia supertipo del tipo base dellarray purché sia un tipo riferimento /* trasforma un array in una lista, copiando * tutti gli elementi di a in l */ static void array2List(T[] a, List l) { for (T o : a) l.add(o) }

Invocazione di metodi generici Nellinvocazione di un metodo generico non è necessario passare largomento di tipo il compilatore inferisce il tipo, se esiste, dai tipi degli argomenti del metodo

Invocazione di metodi generici Continua Object[] oa = new Object[100]; Collection co = new ArrayList (); fromArrayToCollection(oa, co); // T = Object (inferito) String[] sa = new String[100]; Collection cs = new ArrayList (); fromArrayToCollection(sa, cs); // T = String (inferito) fromArrayToCollection(sa, co); // T = Object (inferito) Integer[] ia = new Integer[100]; Float[] fa = new Float[100]; Number[] na = new Number[100]; Collection cn = new ArrayList (); fromArrayToCollection(ia, cn); // T = Number (inferito) fromArrayToCollection(fa, cn); // T = Number (inferito) fromArrayToCollection(na, cn); // T = Number (inferito) fromArrayToCollection(na, co); // T = Object (inferito) fromArrayToCollection(na, cs); // compiler error

Wildarcds vs variabili di tipo Ci sono situazioni in cui è possibili usare equivalentemente wildcards e variabili di tipo. Nella libreria Collection troviamo Continua interface Collection { public boolean containsAll(Collection c); public boolean addAll(Collection c);... }

Wildarcds vs variabili di tipo Queste specifiche possono essere espresse equivalentemente con metodi parametrici Il secondo metodo è parametrico in qualunque sottotipo di E i bounds si possono utilizzare anche con variabili, non solo con wildcards Continua interface Collection { public boolean containsAll(Collection c); public boolean addAll(Collection c);... }

Wildcards e variabili di tipo possono coesistere Notiamo la dipendenza tra i tipi dei due parametri: il tipo della sorgente deve essere un sottotipo del tipo della destinazione Wildarcds vs variabili di tipo Continua interface Collection { public static void copy(List dest, List src)... }

Potremmo analogamente riformulare in modo da evitare le wildcards Come scegliere tra le due soluzioni? Wildarcds vs variabili di tipo Continua interface Collection { public static void copy( dest, List src)... }

In generale, preferiamo le wildcards quando entrambe le soluzioni sono possibili Possiamo darci la seguente rule of thumb se una variabile di tipo ha una unica occorrenza nella specifica di un metodo e il tipo non è il target di un operazione di modifica utilizziamo una wildcard al posto della variabile Wildarcds vs variabili di tipo

Variabili di Tipo e Bounds Abbiamo visto che possiamo definire bounds anche per variabili di tipo (non solo wildcards) Un caso paradigmatico public static > T max(Collection coll) { T candidate = coll.iterator().next(); for (T e : coll) if candidate.compareTo(e) < 0) candidate = e; return candidate; }

Variabili di Tipo e Bounds Il bound su una variabile impone vincoli sulla variabile, determinando quali metodi possono essere utilizzati su valori del tipo variabile Qui il bound è ricorsivo: informa che i valori con cui operiamo forniscono un metodo compareTo() che gli argomenti del metodo devono essere dello stesso tipo dei valori public static > T max(T max(List coll)

Generics e erasure I tipi generici sono significativi a compile-time La JVM opera invece con tipi raw Il tipo raw è ottenuto da un tipo generico mediante un processo detto erasure che rimuove le variabili di tipo il bycode generato da un tipo generico è lo stesso che viene generato dal corrispondente tipo raw.

Generics e erasure Generano lo stesso bytecode List words = new ArrayList (); words.add(hi); words.add(there); String welcome = words.get(0) + words.get(1); List words = new ArrayList(); words.add(hi); words.add(there); String welcome = (String)words.get(0) + (String)words.get(1);

Generics e erasure Cast-iron guarantee i cast impliciti che vengono aggiunti dalla compilazione di codice generico non falliscono mai.

Constraining Type Variables Very occasionally, you need to supply two or more type bounds extends, when applied to type variables, actually means "extends or implements" The bounds can be either classes or interfaces Type variable can be replaced with a class or interface type

Raw Types For example, generic class Pair turns into the following raw class: public class Pair { public Pair(Object firstElement, Object secondElement) { first = firstElement; second = secondElement; } public Object getFirst() { return first; } public Object getSecond() { return second; } private Object first; private Object second; }

Raw Types Knowing about raw types helps you understand limitations of Java generics For example, you cannot replace type variables with primitive types

Self Check 9.What is the erasure of the print method in Section 22.3? 10.What is the raw type of the LinkedList class in Section 22.2?

Answers 10.The LinkedList class of Chapter 20. public static void print(Object[] a) { for (Object e : a) System.out.print(e + " "); System.out.println(); }

Chapter 21 Advanced Data Structures

Chapter Goals To learn about the set and map data types To understand the implementation of hash tables To be able to program hash functions To learn about binary trees To be able to use tree sets and tree maps Continued

Chapter Goals To become familiar with the heap data structure To learn how to implement the priority queue data type To understand how to use heaps for sorting

Sets Set: unordered collection of distinct elements Elements can be added, located, and removed Sets don't have duplicates

A Set of Printers Figure 1: A Set of Printers

Fundamental Operations on a Set Adding an element Adding an element has no effect if the element is already in the set Removing an element Attempting to remove an element that isn't in the set is silently ignored Containment testing (does the set contain a given object?) Listing all elements (in arbitrary order)

Sets We could use a linked list to implement a set Adding, removing, and containment testing would be relatively slow There are data structures that can handle these operations much more quickly Hash tables Trees Continued

Sets Standard Java library provides set implementations based on both data structures HashSet TreeSet Both of these data structures implement the Set interface

Set Classes and Interface in the Standard Library Figure 2: Set Classes and Interfaces in the Standard Library

Iterator Use an iterator to visit all elements in a set A set iterator does not visit the elements in the order in which they were inserted An element can not be added to a set at an iterator position A set element can be removed at an iterator position

Code for Creating and Using a Hash Set //Creating a hash set Set names = new HashSet (); //Adding an element names.add("Romeo"); //Removing an element names.remove("Juliet"); //Is element in set if (names.contains("Juliet") {...}

Listing All Elements with an Iterator Iterator iter = names.iterator(); while (iter.hasNext()) { String name = iter.next(); Do something with name } // Or, using the "for each" loop for (String name : names) { Do something with name }

File SetTester.java 01: import java.util.HashSet; 02: import java.util.Iterator; 03: import java.util.Scanner; 04: import java.util.Set; 05: 06: 07: /** 08: This program demonstrates a set of strings. The user 09: can add and remove strings. 10: */ 11: public class SetTester 12: { 13: public static void main(String[] args) 14: { 15: Set names = new HashSet (); 16: Scanner in = new Scanner(System.in); 17: Continued

File SetTester.java 18: boolean done = false; 19: while (!done) 20: { 21: System.out.print("Add name, Q when done: "); 22: String input = in.next(); 23: if (input.equalsIgnoreCase("Q")) 24: done = true; 25: else 26: { 27: names.add(input); 28: print(names); 29: } 30: } 31: 32: done = false; 33: while (!done) 34: { Continued

File SetTester.java 35: System.out.println("Remove name, Q when done"); 36: String input = in.next(); 37: if (input.equalsIgnoreCase("Q")) 38: done = true; 39: else 40: { 41: names.remove(input); 42: print(names); 43: } 44: } 45: } 46: 47: /** 48: Prints the contents of a set of strings. s a set of strings 50: */ 51: private static void print(Set s) 52: { Continued

File SetTester.java 53: System.out.print("{ "); 54: for (String element : s) 55: { 56: System.out.print(element); 57: System.out.print(" "); 58: } 59: System.out.println("}"); 60: } 61: } 62: 63: Continued

File SetTester.java Output Add name, Q when done: Dick { Dick } Add name, Q when done: Tom { Tom Dick } Add name, Q when done: Harry { Harry Tom Dick } Add name, Q when done: Tom { Harry Tom Dick } Add name, Q when done: Q Remove name, Q when done: Tom { Harry Dick } Remove name, Q when done: Jerry { Harry Dick } Remove name, Q when done: Q

Self Test 1.Arrays and lists remember the order in which you added elements; sets do not. Why would you want to use a set instead of an array or list? 2.Why are set iterators different from list iterators?

Answers 1.Efficient set implementations can quickly test whether a given element is a member of the set. 2.Sets do not have an ordering, so it doesn't make sense to add an element at a particular iterator position, or to traverse a set backwards.

Maps A map keeps associations between key and value objects Mathematically speaking, a map is a function from one set, the key set, to another set, the value set Every key in a map has a unique value A value may be associated with several keys Classes that implement the Map interface HashMap TreeMap

An Example of a Map Figure 3: An Example of a Map

Map Classes and Interfaces Figure 4: Map Classes and Interfaces in the Standard Library

Code for Creating and Using a HashMap //Changing an existing association favoriteColor.put("Juliet",Color.RED); //Removing a key and its associated value favoriteColors.remove("Juliet");

Code for Creating and Using a HashMap //Creating a HashMap Map favoriteColors = new HashMap (); //Adding an association favoriteColors.put("Juliet", Color.PINK); //Changing an existing association favoriteColor.put("Juliet",Color.RED); Continued

Code for Creating and Using a HashMap //Getting the value associated with a key Color julietsFavoriteColor = favoriteColors.get("Juliet"); //Removing a key and its associated value favoriteColors.remove("Juliet");

Printing Key/Value Pairs Set keySet = m.keySet(); for (String key : keySet) { Color value = m.get(key); System.out.println(key + "->" + value); }

File MapTester.java 01: import java.awt.Color; 02: import java.util.HashMap; 03: import java.util.Iterator; 04: import java.util.Map; 05: import java.util.Set; 06: 07: /** 08: This program tests a map that maps names to colors. 09: */ 10: public class MapTester 11: { 12: public static void main(String[] args) 13: { 14: Map favoriteColors 15: = new HashMap (); 16: favoriteColors.put("Juliet", Color.pink); 17: favoriteColors.put("Romeo", Color.green); Continued

File MapTester.java 18: favoriteColors.put("Adam", Color.blue); 19: favoriteColors.put("Eve", Color.pink); 20: 21: Set keySet = favoriteColors.keySet(); 22: for (String key : keySet) 23: { 24: Color value = favoriteColors.get(key); 25: System.out.println(key + "->" + value); 26: } 27: } 28: } Continued

File MapTester.java Output Romeo->java.awt.Color[r=0,g=255,b=0] Eve->java.awt.Color[r=255,g=175,b=175] Adam->java.awt.Color[r=0,g=0,b=255] Juliet->java.awt.Color[r=255,g=175,b=175]

Self Check 3.What is the difference between a set and a map? 4.Why is the collection of the keys of a map a set?

Answers 3.A set stores elements. A map stores associations between keys and values. 4.The ordering does not matter, and you cannot have duplicates.

Hash Tables Hashing can be used to find elements in a data structure quickly without making a linear search A hash table can be used to implement sets and maps A hash function computes an integer value (called the hash code) from an object Continued

Hash Tables A good hash function minimizes collisions– identical hash codes for different objects To compute the hash code of object x : int h = x.hashCode();

Sample Strings and Their Hash Codes StringHash Code "Adam" "Eve"70068 "Harry" "Jim"74478 "Joe"74676 "Juliet" "Katherine" "Sue"83491

Simplistic Implementation of a Hash Table To implement Generate hash codes for objects Make an array Insert each object at the location of its hash code To test if an object is contained in the set Compute its hash code Check if the array position with that hash code is already occupied

Simplistic Implementation of a Hash Table Figure 5: A Simplistic Implementation of a Hash Table

Problems with Simplistic Implementation It is not possible to allocate an array that is large enough to hold all possible integer index positions It is possible for two different objects to have the same hash code

Solutions Pick a reasonable array size and reduce the hash codes to fall inside the array When elements have the same hash code: Use a node sequence to store multiple objects in the same array position These node sequences are called buckets int h = x.hashCode(); if (h < 0) h = -h; h = h % size;

Hash Table with Buckets to Store Elements with Same Hash Code Figure 6: A Hash Table with Buckets to Store Elements with Same Hash Code

Algorithm for Finding an Object x in a Hash Table Get the index h into the hash table Compute the hash code Reduce it modulo the table size Iterate through the elements of the bucket at position h For each element of the bucket, check whether it is equal to x If a match is found among the elements of that bucket, then x is in the set Otherwise, x is not in the set

Hash Tables A hash table can be implemented as an array of buckets Buckets are sequences of nodes that hold elements with the same hash code If there are few collisions, then adding, locating, and removing hash table elements takes constant time Big-Oh notation: O(1) Continued

Hash Tables For this algorithm to be effective, the bucket sizes must be small The table size should be a prime number larger than the expected number of elements An excess capacity of 30% is typically recommended

Hash Tables Adding an element: simple extension of the algorithm for finding an object Compute the hash code to locate the bucket in which the element should be inserted Try finding the object in that bucket If it is already present, do nothing; otherwise, insert it Continued

Hash Tables Removing an element is equally simple Compute the hash code to locate the bucket in which the element should be inserted Try finding the object in that bucket If it is present, remove it; otherwise, do nothing If there are few collisions, adding or removing takes O(1) time

File HashSet.java 001: import java.util.AbstractSet; 002: import java.util.Iterator; 003: import java.util.NoSuchElementException; 004: 005: /** 006: A hash set stores an unordered collection of objects, using 007: a hash table. 008: */ 009: public class HashSet extends AbstractSet 010: { 011: /** 012: Constructs a hash table. bucketsLength the length of the buckets array 014: */ 015: public HashSet(int bucketsLength) 016: { Continued

File HashSet.java 017: buckets = new Node[bucketsLength]; 018: size = 0; 019: } 020: 021: /** 022: Tests for set membership. x an object true if x is an element of this set 025: */ 026: public boolean contains(Object x) 027: { 028: int h = x.hashCode(); 029: if (h < 0) h = -h; 030: h = h % buckets.length; 031: 032: Node current = buckets[h]; 033: while (current != null) 034: { Continued

File HashSet.java 035: if (current.data.equals(x)) return true; 036: current = current.next; 037: } 038: return false; 039: } 040: 041: /** 042: Adds an element to this set. x an object true if x is a new object, false if x was 045: already in the set 046: */ 047: public boolean add(Object x) 048: { 049: int h = x.hashCode(); 050: if (h < 0) h = -h; 051: h = h % buckets.length; 052: Continued

File HashSet.java 053: Node current = buckets[h]; 054: while (current != null) 055: { 056: if (current.data.equals(x)) 057: return false; // Already in the set 058: current = current.next; 059: } 060: Node newNode = new Node(); 061: newNode.data = x; 062: newNode.next = buckets[h]; 063: buckets[h] = newNode; 064: size++; 065: return true; 066: } 067: Continued

File HashSet.java 068: /** 069: Removes an object from this set. x an object true if x was removed from this set, false 072: if x was not an element of this set 073: */ 074: public boolean remove(Object x) 075: { 076: int h = x.hashCode(); 077: if (h < 0) h = -h; 078: h = h % buckets.length; 079: 080: Node current = buckets[h]; 081: Node previous = null; 082: while (current != null) 083: { 084: if (current.data.equals(x)) 085: { Continued

File HashSet.java 086: if (previous == null) buckets[h] = current.next; 087: else previous.next = current.next; 088: size--; 089: return true; 090: } 091: previous = current; 092: current = current.next; 093: } 094: return false; 095: } 096: 097: /** 098: Returns an iterator that traverses the elements of this set. a hash set iterator 100: */ 101: public Iterator iterator() 102: { 103: return new HashSetIterator(); 104: } Continued

File HashSet.java 105: 106: /** 107: Gets the number of elements in this set. the number of elements 109: */ 110: public int size() 111: { 112: return size; 113: } 114: 115: private Node[] buckets; 116: private int size; 117: 118: private class Node 119: { 120: public Object data; 121: public Node next; 122: } 123: Continued

File HashSet.java 124: private class HashSetIterator implements Iterator 125: { 126: /** 127: Constructs a hash set iterator that points to the 128: first element of the hash set. 129: */ 130: public HashSetIterator() 131: { 132: current = null; 133: bucket = -1; 134: previous = null; 135: previousBucket = -1; 136: } 137: 138: public boolean hasNext() 139: { 140: if (current != null && current.next != null) 141: return true; Continued

File HashSet.java 142: for (int b = bucket + 1; b < buckets.length; b++) 143: if (buckets[b] != null) return true; 144: return false; 145: } 146: 147: public Object next() 148: { 149: previous = current; 150: previousBucket = bucket; 151: if (current == null || current.next == null) 152: { 153: // Move to next bucket 154: bucket++; 155: 156: while (bucket < buckets.length 157: && buckets[bucket] == null) 158: bucket++; Continued

File HashSet.java 159: if (bucket < buckets.length) 160: current = buckets[bucket]; 161: else 162: throw new NoSuchElementException(); 163: } 164: else // Move to next element in bucket 165: current = current.next; 166: return current.data; 167: } 168: 169: public void remove() 170: { 171: if (previous != null && previous.next == current) 172: previous.next = current.next; 173: else if (previousBucket < bucket) 174: buckets[bucket] = current.next; 175: else 176: throw new IllegalStateException(); Continued

File HashSet.java 177: current = previous; 178: bucket = previousBucket; 179: } 180: 181: private int bucket; 182: private Node current; 183: private int previousBucket; 184: private Node previous; 185: } 186: }

File SetTester.java 01: import java.util.Iterator; 02: import java.util.Set; 03: 04: /** 05: This program tests the hash set class. 06: */ 07: public class SetTester 08: { 09: public static void main(String[] args) 10: { 11: HashSet names = new HashSet(101); // 101 is a prime 12: 13: names.add("Sue"); 14: names.add("Harry"); 15: names.add("Nina"); 16: names.add("Susannah"); 17: names.add("Larry"); 18: names.add("Eve"); Continued

File SetTester.java 19: names.add("Sarah"); 20: names.add("Adam"); 21: names.add("Tony"); 22: names.add("Katherine"); 23: names.add("Juliet"); 24: names.add("Romeo"); 25: names.remove("Romeo"); 26: names.remove("George"); 27: 28: Iterator iter = names.iterator(); 29: while (iter.hasNext()) 30: System.out.println(iter.next()); 31: } 32: } Continued

File SetTester.java Output Harry Sue Nina Susannah Larry Eve Sarah Adam Juliet Katherine Tony

Self Check 5.If a hash function returns 0 for all values, will the HashSet work correctly? 6.What does the hasNext method of the HashSetIterator do when it has reached the end of a bucket?

Answers 5.Yes, the hash set will work correctly. All elements will be inserted into a single bucket. 6.It locates the next bucket in the bucket array and points to its first element.