Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di...

29
1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo di tipo! Occorre un altro modo per esprimere genericità, che consenta un controllo di tipo a compile time type safety: "se si compila, è certamente corretto" Java 1.5 introduce i tipi parametrici ("generici") Il tipo può essere un parametro: in funzioni statiche, in classi e metodi di classi notazione <TIPO> Si possono definire relazioni fra "tipi generici“ recupera il "lato buono" dell'ereditarietà fra collezioni, inquadrandolo in un contesto solido.

Transcript of Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di...

Page 1: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

1

Generic

Contenitori generici per oggetti realizzati

tramite il concetto di tipo parametrico

IL NUOVO APPROCCIO (java 1.5)È sbagliato abolire il controllo di tipo!

Occorre un altro modo per esprimere genericità, che consenta un controllo di tipo a compile time

type safety: "se si compila, è certamente corretto"Java 1.5 introduce i tipi parametrici ("generici")

Il tipo può essere un parametro:in funzioni statiche, in classi e metodi di classi notazione <TIPO>Si possono definire relazioni fra "tipi generici“recupera il "lato buono" dell'ereditarietà fra collezioni, inquadrandolo in un contesto solido.

Page 2: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

2

Generics

Un generic è un metodo che è ricompilato con differenti tipi secondo le necessità (simile ai template C++)Svantaggi:

Invece di : List words = new ArrayList();Si deve definire:

ArrayLIst<String> words = new ArrayList<String>();

Vantaggi:Fornisce una migliore gestione del type checking durante la compilazioneEvita il casting da Object. I.e., invece di

String title = ((String) words.get(i)).toUppercase();utilizzaremo

String title = words.get(i).toUppercase();

Esempio di classe parametricaclass tipo <T> {

T attributo;public tipo (T x){attributo = x;}public T getValue() {return attributo;}}

Page 3: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

3

Uso della classe parametricapublic class Prova {

public static void main(String []s){tipo <String> p1 = new tipo<String>(s[0]);tipo <Integer> p2 = new tipo<Integer>(10);String a = p1.getValue();System.out.println(a);Integer b = p2.getValue();System.out.println(b);

}}

Tutta la JFC è stata riscritta per far uso dei generici

Anche classi preesistenti (come Vector) sono state reingegnerizzate e riscritte in accordo al nuovo idiomaLe operazioni sulla JFC "generica" si dicono checked (controllate) o type-safe (sicure come tipo)

Page 4: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

4

public interface List<E> { void add(E x);Iterator<E> iterator();

}

public interface Iterator<E> { E next();boolean hasNext();

}

List<Integer> myIntList = new LinkedList<Integer>(); // 1’myIntList.add(new Integer(0)); //2’Integer x = myIntList.iterator().next(); // 3’

List myIntList = new LinkedList(); // 1myIntList.add(new Integer(0)); // 2Integer x = (Integer) myIntList.iterator().next(); // 3

Tipi parametrizzati Tutte le occorrenze del parametro “formal type” (E in questo caso) sono sostituite dagli argomenti i “actual type” (in questo caso Integer).

Page 5: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

5

List<String> ls = new ArrayList<String>(); //1List<Object> lo = ls; //2

L’istruzione 2 genera un errore in compilazione

In generale, se C2 è una classe derivata da C1 e G è una dichiarazione generica, non è vero che G<C2> è un tipo derivato da G<C1>.

Tipi generici ed Ereditarietà

Verso iI concetto di"tipo parametrico variante"

Page 6: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

6

Abbiamo visto che, se B deriva da A, NON si può dire che una collezione di elementi di B derivi dalla collezione di elementi di A, perché in generale ciò non ha senso (operazioni impossibili)

ALCUNE operazioni potrebbero anche essere sicure (negli array, la lettura), ma ciò non è vero in generale.

CLASSI GENERICHE ed EREDITARIETÀ

Consideriamo la classe generica LinkedList <T>:prendiamo due sue "istanziazioni"

LinkedList <Number> LinkedList<Integer>

Sono due tipi diversi, incompatibili fra loro!Si evita così il rischio di situazioni "apparentemente giuste ma in realtà sbagliate" stile array.Per verificarlo, immaginiamo di creare due liste:

LinkedList<Number> l1 = new LinkedList<Number>();LinkedList<Integer> l2 = new LinkedList<Integer>();

e consideriamo i due possibili assegnamenti:l1 = l2 //errorel2 = l1 //errore

Page 7: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

7

Tipi parametrici variantiCovarianza, controvarianza,

bivarianza

Dai TIPI GENERICI a TIPI PARAMETRICIVARIANTI ("WILDCARD")

L'esperimento precedente ha mostrato che non ha senso cercare una compatibilitàgenerale fra tipi parametrici, perché non può esistere.Ha senso invece cercare compatibilità fra casi specifici e precisamente fra tipi di parametri di singoli metodi.Perciò, alla normale notazione dei tipi generici List<T>, usata per creare oggetti, si affianca una nuova notazione, pensata esplicitamente per esprimere i tipi accettabili come parametri in singoli metodiSi parla quindi di tipi parametrici varianti, in Java più brevemente detti WILDCARD.

Page 8: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

8

WILDCARD, ovvero TIPI COVARIANTI,CONTROVARIANTI, BIVARIANTI

Alla luce di ciò:la notazione List<T> denota il normale tipo genericoil tipo covariante List<? extends T>

fattorizza le proprietà dei List<X> in cui X estende Tsi usa per specificare tipi che consentono solo "letture"

il tipo controvariante List<? super T>fattorizza le proprietà dei List<X> in cui X è esteso da Tsi usa per specificare tipi che consentono solo "scritture"

il tipo bivariante List<?>fattorizza tutti i List<T> senza distinzionesi usa per specificare tipi che non consentono né letture né scritture (ma possono servire comunque…)

Wildcardsvoid printCollection(Collection c) {

Iterator i = c.iterator();for (k = 0; k < c.size(); k++) {

System.out.println(i.next());}}void printCollection(Collection<Object> c) { for (Object e : c) { System.out.println(e);}}

void printCollection(Collection<?> c) { for (Object e : c) { System.out.println(e);}}

Wildcards

Page 9: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

9

Esempiopublic class MyList<T> {

private T head;private MyList<T> tail;public T getHead(){ return head; }public <E extends T> void setHead(E element){

head=element; }}

MyList<Number> list1 = new MyList<Number>();MyList<Integer> list2 = new MyList<Integer>();list1.setHead( new Double(1.4) ); // OK!list1.setHead( list2.getHead() ); // OK!

Esempiopublic class MyList<T> {

private T head;private MyList<T> tail;public T getHead(){ return head; }public <E extends T> void setHead(E element){

head=element; }public void setTail(MyList<T> l){ tail=l; }public MyList<? extends T> getTail(){ return tail; }

}

MyList<? extends Number> list3 = list1.getTail();MyList<? extends Number> list4 = list2.getTail();MyList<? extends Integer> list5 = list2.getTail();I primi due restituiscono una lista di Number, compatibile col tipo "lista di qualcosa che estenda Number“Il terzo restituisce una lista di Integer, compatibile col tipo "lista di qualcosa che estenda Integer"

Restituisce una lista di elementi di tipo T o più specifico di T

Page 10: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

10

public class MyList<T> {private T head;private MyList<? extends T> tail;public T getHead(){ return head; }public <E extends T> void setHead(E element){...}public MyList<? extends T> getTail(){ return tail; }public void setTail(MyList<? extends T> l){ tail=l;}

}Non c'è realmente bisogno che la coda sia una lista di T!Possiamo essere più generici! Conseguentemente, possiamo rilassare il vincolo su setTail, il cui argomento ora può essere una lista di qualunque cosa estenda Tlist1.setTail(list2); // SI', ORA VA BENE!

Si rendono così SELETTIVAMENTE possibili TUTTE e SOLE le operazioni "sensate" e significative!

Riflessioni a posterioriNell'esempio precedente abbiamo usato:

il tipo generico MyList<T> per creare oggetti

MyList<Number>, MyList<Integer>, …tipi covarianti come MyList<? extends Number>

fattorizza le proprietà dei tipi di liste che estendono Number, come MyList<Integer>, MyList<Double>, o MyList<Number> stessa

NON abbiamo invece usato: tipi controvarianti come MyList<? super Number>

fattorizzerebbe le proprietà di tutte le liste di tipi più generici di Number, come ad esempio MyList<Object>

il tipo bivariante MyList<?>

Page 11: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

11

public abstract class Shape { public abstract void draw(Canvas c);}

public class Circle extends Shape { private int x, y, radius;public void draw(Canvas c) { ... }

}

public class Rectangle extends Shape { private int x, y, width, height;public void draw(Canvas c) { ... }

}

public void drawAll(List<Shape> shapes) { for (Shape s: shapes) { s.draw(this);}}

public void drawAll(List<? extends Shape> shapes) { ... }

List<? extends Shape> è un esempio di bounded wildcard. Il simbolo? Sta per un tipo sconosciutoSappiamo che in questo caso tale tipo sconosciuto e un subtype di Shape. Diremo che Shape è un upper bound di una wildcard.

Page 12: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

12

Generic Methods

Supponiamo di voler scrivere un metodo che prende un array di objects è una collection e pone gli oggetti dell’array in una collection.Soluzione

static void fromArrayToCollection(Object[] a, Collection<?> c) { for (Object o : a) { c.add(o); //

compile time error}}

I metodi generici consentono di superare un tale problema.Cosi come in una dichiarazione di tipo, la dichiarazione di un metodo può essere generica cioè parametrizzata rispeotto ad uno o più parametri

static <T> void fromArrayToCollection(T[] a, Collection<T> c)

{ for (T o : a) { c.add(o); // correct}}

Page 13: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

13

Enhanced for loopInvece di

void cancelAll(Collection c) { for (Iterator i = c.iterator(); i.hasNext(); ) {

TimerTask tt = (TimerTask) i.next();tt.cancel();

}}

Si può utilizzare:void cancelAll(Collection<TimerTask> c) {

for (TimerTask task : c)task.cancel();

}

void cancelAll(Collection<TimerTask> c) {foreach TimerTask task of c) //C# notation

task.cancel();}

Le strutture di java.util

Page 14: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

14

ListeNel package java.util

due tipi di listeentrambe implementano l’interfaccia java.util.List

ArrayList: basata su array e indicatore di riempimentoLinkedList:basata su rappresentazione collegata

Attenzione - i due tipi di liste hanno prestazioni diverse nelle operazioni fondamentali

public class LinkedList<E> extendsAbstractSequentialList<E>

implements List<E>, Deque<E>, Cloneable, Serializable

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

public class ArrayDeque<E> extends AbstractCollection<E>implements Deque<E>, Cloneable, Serializable

public class Vector<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, Serializable

Page 15: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

15

la rappresentazione con array facilita l’accesso agli elementi data la posizione ma penalizza gli inserimenti e le cancellazioni in mezzo alla lista è necessario spostare gli elementi su o giù

ViceversaLinkedList è più lenta nell’accesso agli elementi data la posizione

accedere l’elemento in posizione i richiede la scansione di i riferimentima è più veloce negli inserimenti e nelle cancellazioni (approssimativamente costano quanto la scansione)

Un test di prestazioniBasato su circa 1000 operazionitempi misurati in millisecondi

Page 16: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

16

Considerazioni sulle prestazionigli array sono i più veloci, ma non consentono inserimenti e cancellazioniArrayList è veloce nell’accesso agli elementi, lenta in inserimenti e cancellazioni in mezzoLinkedList è più lenta nell’accesso, ma decisamente piùveloce in inserimenti e canc.Vector è più lenta di entrambe e non dovrebbe essere utilizzata

Di conseguenzanel caso di liste a bassa dinamica, per ridurre i tempi di scansione è opportuno usare ArrayListper liste ad alta dinamica, con frequenti inserimenti e cancellazioni conviene utilizzare LinkedListE che succede se devo cambiare tipo ? es: passare da ArrayList a LinkedList

Linea guidaè opportuno programmare con le interfacce invece che con le implementazionile interfacce riducono l’accoppiamento tra leclassi e semplificano i cambiamenti

Nel caso delle listeè opportuno utilizzarle per quanto possibile attraverso riferimenti di tipo java.util.List

In questo modole modifiche sono semplificatebasta cambiare le poche istruzioni in cui gli oggetti di tipo lista sono creati cambiando la classe usata per l’implementazioneil resto dell’applicazione resta intattai metodi si comportano polimorficamente e viene utilizzata la nuova implementazione

Page 17: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

17

IteratoriAttenzione

in questo approccio, quando manipolo la lista devo tenere in considerazione che l’implementazione potrebbe cambiare

In particolaredevo fare attenzione a non basare la scrittura del codice su una o l’altra delle implementazioniUn’operazione critica: la scansione

Il modo tipico di scandire una lista utilizzandoindici interi

for (int i = 0; i < lista.size(); i++) {Object o = lista.get(i);// operazioni su o}

IteratoriQuesto tipo di scansione

è particolarmente adatto ad ArrayList (il metodo get viene eseguito rapidamente)ma disastrosamente lenta su LinkedList

Perchè ?perchè come detto l’accesso all’elemento in posizione i di una LinkedList richiede di scandire i elementi (i operazioni circa)

Detta n la dimensione della lista 1 + 2 + 3 + 4 + ... + npari circa a n(n +1)/2, ovvero dell’ordine di n2

es: per una lista di 100 elementi: 5000nel caso di ArrayList: circa 100 operazioni

In casi normaliil problema non sorge (liste piccole)ma in alcuni casi si tratta di un costo di calcolo che può diventare inaccettabile

Page 18: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

18

Il problemala scansione attraverso indici interi NON è la scansione più

naturale per LinkedListArrayList

implementazione basata su indici scansione naturale basata su indici

LinkedListimplementazione basata su riferimenti

scansione naturale basata su riferimentiIdealmente

vorrei che per ciascuna tipologia di lista potesse essere utilizzata automaticamente la scansione più adattasenza che il programmatore se ne debba preoccupare

Attenzionein questo caso il polimorfismo da solo non basta

La scansione della lista è un’operazione che deve necessariamente essere effettuata da un oggetto diverso dalla lista, non posso quindi semplicemente sovrascrivere il metodo “scandisciti()” e utilizzarlo polimorficamente devo necessariamente definire altri oggetti la cui responsabilità èquella di scandire la lista

Soluzioneutilizzare un oggetto “iteratore”

Iteratoreoggetto specializzato nella scansione di una listafornisce al programmare un’interfaccia per effettuare la scansione in modo indipendente dalla strategia di scansione concreta (indici, puntatori, ecc.) implementa la scansione in modo ottimale per ciascun tipo di lista

Page 19: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

19

L’utilizzo in java.utilinterfaccia java.util.Iterator, che prevede i seguenti metodi

Object next() per spostarsi in avantiboolean hasNext() per fermarsi

esiste poi una implementazione per ArrayListed una implementazione per LinkedList

Iteratore per ArrayListutilizza indici interi

Iteratore per LinkedListscandisce la lista usando i riferimenti

Come si ottiene l’iteratore ?utilizzando il metodo Iterator iterator() di java.util.List

Dettagli sugli iteratori di java.utilsostanzialmente si basano sui metodi next() e previous() forniti dalle due listesono però più complicati di quanto si pensa dal momento che consentono anche di modificare la lista durante la scansioneattraverso il metodo remove()senza doversi preoccupare della consistenzadei riferimenti

Page 20: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

20

Una novità di J2SE 1.5il ciclo for migliorato (“enhanced for loop”)un modo sintatticamente compatto per utilizzare un iteratore su una collezione

Sintassifor (<Tipo> <riferimento> : <Collezione>)

{<operazioni su <riferimento>>}

Ricerca e rimozione di un elementoE’ necessario che la classe degli elementi cotenuti nella lista implementi il metodo equals

Page 21: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

21

MappeUna mappa, ovvero un dizionario associativo

classe java.util.HashMapimplementa l’interfaccia java.util.Map

Dizionario associativocollezione in cui i riferimenti sono salvati con un “nome”, detto chiavetipicamente una stringapossono successivamente essere recuperati rapidamente utilizzando la chiave

Page 22: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

22

public interface Map<K,V>Principali metodi

V put(K key, V value)void putAll(Map<? extends K,? extends V> m)V get(Object key)V remove(Object key)

Implementazioni java.util.HashMapjava.util.TreeMapjava.util.Hashtable

metodi principali di java.util.Mapvoid put(Object chiave, Object riferimento)Object get(Object chiave)Object remove(Object chiave)int size()

Le principali implementazionijava.util.HashMapjava.util.TreeMapjava.util.Hashtable (versione legacy)

Page 23: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

23

Differenze rispetto alle listein una mappa non sono significative le posizioni degli elementi ma le chiavile ricerche sulla base della chiave sono enormemente facilitate (nella lista richiederebbero una scansione)utilizzata tipicamente quando più che le scansioni sono importanti le ricerche

Attenzione peròad ogni chiave può essere associato un unico oggettoput successive con la stessa chiave sostituiscono i valori precedentinon può essere usata quando possono esserci più valori per la stessa chiave

HashMapUn requisito fondamentale per le mappela rapidità di inserimento e cancellazione

L’implementazione fondamentaleHashMap

di gran lunga la più veloce

La tecnica sottostantetecnica di hashing ovvero basata su “funzioni di hashing”

Page 24: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

24

HashMapFunzione di hash

funzione che trasforma un valore (“chiave”) di lunghezza variabile in uno di lunghezza fissa (“hash”della chiave)

Caratteristica tipica di una funzione hashl’hash deve essere calcolabile rapidamente

Classificazione delle funzioni hashfunzioni con collisioni o prive di collisioni

Funzione priva di collisionenon ci sono due valori per cui l’hash è ugualepossibile solo se i valori sono finiti

Funzione con collisionepiù valori possono avere lo stesso valore di hashcaso tipico

HashMapImplementazione di put() nella HashMap

la mappa mantiene gli oggetti in un array di N riferimenti a liste (dette “bucket”)ogni elemento della lista memorizza una coppia <chiave, riferimento>viene calcolato il valore della funzione di hash sulla chiave e poi viene applicato un operatore modulo per ridurlo ad un numero tra 0 e N – 1in questo modo si ottiene un indice nell’array; la coppia <chiave, riferimento> viene aggiunta in coda al bucket della posizione ottenuta

Page 25: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

25

HashMapImplementazione di get() in HashMap

viene calcolato il valore di hash della chiave per risalire al bucket (indice nell’array) viene scandito il bucket e la chiave viene confrontata con ogni chiavese viene trovata una chiave identica a quella cercata, viene restituito il riferimentoaltrimenti viene restituito null

Due operazioni fondamentaliil calcolo della funzione di hashil confronto tra le chiavi

Calcolo della funzione di hashviene usato il metodo hashCode() ereditato da Object

Confronto tra le chiaviviene utilizzato il metodo equals() ereditato da Object

Page 26: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

26

HashMapNota

le implementazioni standard sono basate sull’indirizzo in memoriapotrebbero non essere quelle adatte a fare hashing in alcuni casi

Nelle classi principali della piattaformasono ridefinite opportunamente quando è necessario

Di conseguenzaè opportuno utilizzare come chiave per le mappe oggetti di classi note es: String, Integer, ecc.Nel caso in cui questo non sia possibile

per la classe di oggetti da utilizzare come chiavi ènecessario ridefinire opportunamente hashCode() ed equals()

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, SerializableCapacity: numero di buckets nella hash table, Load factor e’ la misuradi quanto piena puo ‘ essere l’hash table prima di un resize (0,75)Costruttori

HashMap() costruisce una HashMap vuota con capacity =16 e load factor = 0.75

HashMap(int initialCapacity) costruisce una HashMap vuota con capacity = initialCapacity e load factor = 0.75

HashMap(int initialCapacity, float loadFactor) costruisce HashMap con i valori specificati

HashMap(Map<? extends K,? extends V> m) costruisce una HashMap con lo stesso mappings della mappa scecificata.

Page 27: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

27

InsiemiAltre classi significative delle collezioni

interface java.util.Set: rappresenta una collezione non ordinata e priva di duplicatidue principali implementazioni: HashSet e TreeSetinterface java.util.Collection: rappresenta una collezione generica (può essere un insieme oppure una lista)tutte le collezioni sono scandibili con iteratori

A cosa servono gli insiemi ?possono essere quasi sempre sostituiti dalle listein alcuni casi sono più naturali

Esempio: Gestione Appuntamentipotrei utilizzare un oggetto di tipo java.util.Set per rappresentare l’insieme dei partecipanti ad una Riunione

InsiemiA questo punto possiamo vedere come scandire una mappadue metodi principali

ottengo l’insieme delle chiavi con Set keySet() e scandisco l’insieme con un iteratore e prelevo dalla mappa tutti gli elementiottengo la collezione dei valori con il metodo Collection values() ottengo un iteratore dalla collezione e scandisco tutti gli elementi

Perchè Set e Collection ?per rispettare la regola secondo cui si programma con le interfacce e non con le implementazioniInfatti

Una HashMap è una collezione non ordinata cioe mantiene un insieme di chiavi e non una lista

Page 28: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

28

OrdinamentiIn Java

l’ordinamento delle collezioni è una funzionalità offerta dalla piattaforma es: java.util.Collections.sort(java.util.List list) ma bisogna rispettare delle regole

In particolareper ordinare una collezione di riferimenti, gli oggetti relatividevono essere confrontabilirispetto ad una precisa relazione di ordine

Esempiola lista degli Impegniun ordinamento possibile: per orarioun altro ordinamento: in ordine alfabetico rispetto alla descrizioneun altro ordinamento ancora: rispetto al luogo di svolgimentoper poter ordinare una lista di impegnibisogna decidere il criterio di ordinamento

In Javagli oggetti ordinabili devono implementare l’interfaccia java.lang.Comparable

java.lang.Comparableprevede un unico metodoint compareTo(Object o)risultato > 0 se this segue o nell’ordinamentorisultato < 0 se this precede o nell’ordinam.risultato = 0 se this non precede nè segue o

Page 29: Generic - Giuseppe · 1 Generic Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico IL NUOVO APPROCCIO (java 1.5) È sbagliato abolire il controllo

29

Ordinamenti

Notal’utilizzo di Comparable prevede che sia possibile cambiare il codice delle classi che definiscono gli oggetti da ordinareper implementare Comparable e definire compareTo()se questo non è possibile, è possibile utilizzare un approccio alternativoutilizzare un oggetto esterno comparatore

L’interfaccia java.util.Comparatorunico metodo: int compare(Object o1, Object o2)gli oggetti che implementano l’interfaccia sono quindi capaci di confrontare oggetti secondo algoritmi specifici