strutture dati in java - diit.unict.it · package java.util strutture dati in java ... i resizable...

40
1 Package java.util STRUTTURE DATI IN JAVA Molto spesso, una computazione si basa su una o più strutture dati, di vario tipo: insiemi, code, stack, tabelle, liste, alberi… Data la loro importanza, Java ne offre un’ampia scelta nella Java Collection Framework (JCF) interfacce che definiscono insiemi di funzionalità classi che ne forniscono varie implementazioni Sono contenitori "generici" per oggetti fino a JDK 1.4, si usava Object come tipo generico da Java 1.5 in poi: supporto ai TIPI GENERICI

Upload: vandung

Post on 15-Apr-2018

241 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

1

Package java.util

STRUTTURE DATI IN JAVA Molto spesso, una computazione si basa su una o più

strutture dati, di vario tipo:

insiemi, code, stack, tabelle, liste, alberi…

Data la loro importanza, Java ne offre un’ampia scelta nella Java Collection Framework (JCF)

interfacce che definiscono insiemi di funzionalità

classi che ne forniscono varie implementazioni

Sono contenitori "generici" per oggetti

fino a JDK 1.4, si usava Object come tipo generico

da Java 1.5 in poi: supporto ai TIPI GENERICI

Page 2: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

2

Cosa è una collezione (Collection)? Un oggetto che ragruppa un gruppo di elementi in una

singolo oggetto.

Uso: memorizzare, manipolare e trasmettere dati da un metodo ad un altro.

Tipicalmente rappresentano gruppi di elementi naturalmente collegati:

Una collezione di lettere

Una collezione di numeri di telefono

Cosa è l’ambiente “Collections“?

E una architettura unificata per manipolare collezioni. Un framework di collection contiene tre elementi:

Interfaces Implementazion Algoritmi

Esempi C++ Standard Template Library (STL) Smalltalk's collection classes. Java’s collection framework

Vantaggi Riduce lo sforzo di programmazione Accresse la velocità e la qualità di programmazione Interoperabilita fra API scorrelate Riduce lo sforzo di imparare ed utilizzare nuove API Riduce lo sforzo per prograttare nuove API Riuso del software

Page 3: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

3

Collections Framework Interfacce

Abstract data types rappresentanti le collezioni.

Permentono di manipolare le collezioni indipententemente dai dettagli delle loro implementazioni.

In un linguaggio object-oriented come Java, queste interfacce formano una gerarchia

Algoritmi Metodi che eseguono utili computazioni come ricerca,

ordinamento sugli oggetti che implementano le interfaccie

Questi algoritmi sono polimorfi in quanto lo stesso metodo può essere utilizzato su molte differenti implementazioni della stessa interfaccia.

Map

SortedMap

SortedSet

Set List

Interfacce di Collections

Collection

Page 4: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

4

JCF: QUADRO GENERALE Implementazioni fondamentali per le liste: ArrayList,LinkedList, Vector per le tabelle hash: HashMap, HashSet, Hashtable per gli alberi: TreeSet, TreeMap (implementano

rispettivamente SortedSet e SortedMap) Due parole sulle classi di implementazione: le linked list sono liste realizzate con puntatori i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le tabelle hash sono tabelle realizzate tramite funzioni

hash, ossia funzioni che associano una entità a un valore tramite una funzione matematica.

Contenitori generici per oggetti realizzati tramite il tipo generico Object

Page 5: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

5

JCF "CLASSICA" (fino a Java 1.4) Scelta di fondo: uso del tipo generico Object come mezzo

per ottenere contenitori generici i metodi che aggiungono / tolgono oggetti dalle collezioni

prevedono un parametro di tipo Object i metodi che cercano / restituiscono oggetti dalle collezioni

prevedono un valore di ritorno Object

Conseguenza: si possono aggiungere/togliere alle/dalle collezioni oggetti

di qualunque tipo, TRANNE i tipi primitivi questi ultimi devono prima essere rispettivamente

incapsulati in un oggetto (BOXING) / estratti da un oggetto che li racchiuda (UNBOXING)

Contenitori generici per oggetti realizzati

tramite il concetto di tipo parametrico

Page 6: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

6

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.

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 compilazione

Evita il casting da Object. I.e., invece di

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

Page 7: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

7

Esempio di classe parametrica class tipo <T> {

T attributo;

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

public T getValue() {return attributo;}

}

Uso della classe parametrica public 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);

}

}

Page 8: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

8

Tutta la JFC è stata riscritta per far uso dei generici

Anche classi preesistenti (come Vector) sono state reingegnerizzate e riscritte in accordo al nuovo idioma

Le operazioni sulla JFC "generica" si dicono checked (controllate) o type-safe (sicure come tipo)

public interface List<E> {

void add(E x);

Iterator<E> iterator();

}

public interface Iterator<E> {

E next();

boolean hasNext();

}

Page 9: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

9

List<Integer> myIntList = new LinkedList<Integer>(); // 1’

myIntList.add(new Integer(0)); //2’

Integer x = myIntList.iterator().next(); // 3’

List myIntList = new LinkedList(); // 1

myIntList.add(new Integer(0)); // 2

Integer x = (Integer) myIntList.iterator().next(); // 3

Tipi parametrizzati

Tutte le occorenze del parametro “formal type” (E in questo caso)

sono sostituite dagli argomenti i “actual type” (in questo caso

Integer).

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

List<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>.

Page 10: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

10

Verso iI concetto di

"tipo parametrico variante"

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.

Page 11: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

11

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 //errore

l2 = l1 //errore

Covarianza, controvarianza, bivarianza

Page 12: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

12

Dai TIPI GENERICI a TIPI PARAMETRICI VARIANTI ("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 metodi

Si parla quindi di tipi parametrici varianti, in Java più brevemente detti WILDCARD.

WILDCARD, ovvero TIPI COVARIANTI, CONTROVARIANTI, BIVARIANTI Alla luce di ciò:

la notazione List<T> denota il normale tipo generico

il tipo covariante List<? extends T> fattorizza le proprietà dei List<X> in cui X estende T

si 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 T

si usa per specificare tipi che consentono solo "scritture"

il tipo bivariante List<?> fattorizza tutti i List<T> senza distinzione

si usa per specificare tipi che non consentono né letture né scritture (ma possono servire comunque…)

Page 13: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

13

Wildcards void 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

Esempio public 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!

Page 14: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

14

Esempio public 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

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 T list1.setTail(list2); // SI', ORA VA BENE! Si rendono così SELETTIVAMENTE possibili TUTTE e SOLE le operazioni

"sensate" e significative!

Page 15: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

15

Riflessioni a posteriori Nell'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<?>

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) { ... }

Page 16: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

16

List<? extends Shape> è un esempio di bounded wildcard.

Il simbolo? Sta per un tipo sconosciuto

Sappiamo che in questo caso tale tipo sconosciuto e un subtype di Shape.

Diremo che Shape è un upper bound di una wildcard.

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 }}

Page 17: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

17

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} }

Collection Radice della gerarchi delle collezioni

Rappresenta un gruppo di oggetti detti elementi della collezione.

Alcune implementazioni di Collection consento la duplicazione degli elemente mentre altre no. Alcune sono ordinate altre no.

Collection è utilizzato per passare collezioni e manipolarle con la massima generalità.

Page 18: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

18

Set

Interface Set extends Collection

Modella l’astrazione matematica di insieme

Collezione non ordinata di object

No elementi duplicati

Gli stessi metodi di Collection

Semantica differente

Implementazioni:

AbstractSet, HashSet, LinkedHashSet, TreeSet

Collection

Set

SortedSet

List

SortedSet

Interface SortedSet extends Set

Un insieme che garanisce che l’insieme sia ordinato

Tutti gli elementi inseriti in un sorted set devono implementare l’interfaccia Comparable

Implementazioni: TreeSet

Collection

Set

SortedSet

List

Page 19: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

19

List

Una collezione ordinata (chiamata anche sequenza).

Può contenere elementi duplicati Consente il controllo della posizione nella lista in

cui un elemento è inserito L’accesso agli elemento è eseguito rispoetto al loro

indice intero (posizione). All Known Implementing Classes: AbstractList, ArrayList, LinkedList, Vector

Collection

Set

SortedSet

List

Map

Interface Map (non estente Collection) Un object corrisponde (maps) valori chiave Non contiene chiavi duplicate ogni chiave corrisponde al più un valore Sostituisce la classe astratta java.util.Dictionary L’ordine può essere fornito da classi che implementano l’interfaccia All Known Implementing Classes:

AbstractMap, Attributes, HashMap, Hashtable, IdentityHashMap, RenderingHints, TreeMap, WeakHashMap

Map

SortedMap

Page 20: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

20

SortedMap

public interface SortedMap extends Map

un map che garantisce che è ordinato in ordine crescente.

Tutti gli elementi inseriti in un sorted map devono implementare l’interfaccia Comparable

All Known Implementing Classes:

TreeMap

Map

SortedMap

Implementazioni nel Framework Collections Le implementazioni concrete dell’interfaccia

collection sono strutture dati riutilizzabili

Page 21: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

21

Set Implementations HashSet un insieme associato

con una hash table

TreeSet Implementazione di un

albero binario bilanciato

Impone un ordine nei suoi elementi

HashSet TreeSet

Set

List Implementations

ArrayList

LinkedList

List

Vector

Page 22: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

22

List Implementations ArrayList

Un array ridimenzionabile Asincrono

LinkedList Una lista doppiamente concatenata Pu ò avere performance migliori di ArrayList

Vector Un array ridimenzionabile Sincrono

Map Implementations Map

SortedMap

TreeMap

Hashtable

HashMap

Page 23: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

23

Map Implementations HashMap

Un hash table implementazione di Map

Come Hashtable, ma supporta null keys & values

TreeMap

Un albero binario bilanciato

Impone un ordine nei suoi elementi

Hashtable hash table sincronizzato Implementazione dell’interfaccia Map.

Utility di Collections Framework Interfaces

Collections Arrays

Classes

ListIterator

Iterator Comparator

Page 24: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

24

Iterator public interface Iterator<E> Creato da Collection.iterator() Simile a Enumeration Nome di metodi migliorati Permette una operazione remove() sul item

corrente boolean hasNext()

Returns true if the iteration has more elements. E next()

Returns the next element in the iteration. void remove()

Removes from the underlying Implementazioni: BeanContextSupport.BCSIterator

ListIterator public interface ListIterator<E>extends Iterator<E>

Attraversa la List in ogni direzione

Modifica List durante l’iterazione

Metodi aggiunti:

void add(E e) Inserts the specified element into the list (optional

operation).

boolean hasPrevious() Returns true if this list iterator has more elements when

traversing the list in the reverse direction.

Page 25: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

25

int nextIndex()

Returns the index of the element that would be returned by a subsequent call to next.

E previous()

Returns the previous element in the list.

int previousIndex()

Returns the index of the element that would be returned by a subsequent call to previous.

void set(E e)

Replaces the last element returned by next or previouswith the specified element (optional operation).

java.lang.Object

java.util.AbstractCollection

java.util.AbstractList

java.util.AbstractSequentialList

java.util.LinkedList

List Cloneable Serializable

Collection

Page 26: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

26

Liste Nel package java.util

due tipi di liste

entrambe implementano l’interfaccia java.util.List

ArrayList: basata su array e indicatore di riempimento

LinkedList:basata su rappresentazione collegata

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

public class LinkedList<E> extends

AbstractSequentialList<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 27: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

27

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ù

Viceversa

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

accedere l’elemento in posizione i richiede la scansione di i riferimenti

ma è più veloce negli inserimenti e nelle cancellazioni (approssimativamente costano quanto la scansione)

Un test di prestazioni Basato su circa 1000 operazioni

tempi misurati in millisecondi

Page 28: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

28

Considerazioni sulle prestazioni gli array sono i più veloci, ma non consentono inserimenti e

cancellazioni

ArrayList è veloce nell’accesso agli elementi, lenta in inserimenti e cancellazioni in mezzo

LinkedList è più lenta nell’accesso, ma decisamente più veloce in inserimenti e canc.

Vector è più lenta di entrambe e non dovrebbe essere utilizzata

Di conseguenza

nel caso di liste a bassa dinamica, per ridurre i tempi di scansione è opportuno usare ArrayList

per liste ad alta dinamica, con frequenti inserimenti e cancellazioni conviene utilizzare LinkedList

E che succede se devo cambiare tipo ? es: passare da ArrayList a LinkedList

Linea guida è opportuno programmare con le interfacce invece che con le

implementazioni le 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 modo le modifiche sono semplificate basta cambiare le poche istruzioni in cui gli oggetti di tipo lista sono

creati cambiando laclasse usata per l’implementazione il resto dell’applicazione resta intatta i metodi si comportano polimorficamente e viene utilizzata la nuova

implementazione

Page 29: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

29

Iteratori Attenzione in questo approccio, quando manipolo la lista devo

tenere in considerazione che l’implementazione potrebbe cambiare

In particolare devo fare attenzione a non basare la scrittura del codice

su una o l’altra delle implementaz. Un’operazione critica: la scansione Il modo tipico di scandire una lista utilizzando indici interi for (int i = 0; i < lista.size(); i++) {

Object o = lista.get(i); // operazioni su o }

Iteratori Questo 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 + ... + n pari circa a n(n +1)/2, ovvero dell’ordine di n2

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

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

inaccettabile

Page 30: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

30

Il problema la scansione attraverso indici interi NON è la scansione più naturale per

LinkedList ArrayList implementazione basata su indici >> scansione naturale basata su

indici LinkedList implementazione basata su riferimenti >> scansione naturale basata su

riferimenti Idealmente vorrei che per ciascuna tipologia di lista potesse essere utilizzata

automaticamente la scansione più adatta senza che il programmatore se ne debba preoccupare Attenzione in 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

Soluzione utilizzare un oggetto “iteratore” Iteratore oggetto specializzato nella scansione di una lista fornisce 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 31: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

31

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

Object next() per spostarsi in avanti boolean hasNext() per fermarsi

esiste una implementazione per ArrayList ed una implementazione per LinkedList Iteratore per ArrayList utilizza indici interi Iteratore per LinkedList scandisce la lista usando i riferimenti Come si ottiene l’iteratore ? utilizzando il metodo Iterator iterator() di java.util.List

Dettagli sugli iteratori di java.util

sostanzialmente si basano sui metodi next() e previous() forniti dalle due liste

sono però più complicati di quanto si pensa dal momento che consentono anche di modificare la lista durante la scansione attraverso il metodo remove() senza doversi preoccupare della consistenza dei riferimenti

Page 32: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

32

Ricerca e rimozione di un elemento E’ necessario che la classe degli elementi cotenuti nella

lista implementi il metodo equals

Mappe Una mappa, ovvero un dizionario associativo

classe java.util.HashMap

implementa l’interfaccia java.util.Map

Dizionario associativo

collezione in cui i riferimenti sono salvati con un “nome”, detto chiave

tipicamente una stringa

possono successivamente essere recuperati rapidamente utilizzando la chiave

Page 34: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

34

metodi principali di java.util.Map

void put(Object chiave, Object riferimento)

Object get(Object chiave)

Object remove(Object chiave)

int size()

Le principali implementazioni

java.util.HashMap

java.util.TreeMap

java.util.Hashtable (versione legacy)

Differenze rispetto alle liste

in una mappa non sono significative le posizioni degli elementi ma le chiavi

le 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 oggetto

put successive con la stessa chiave sostituiscono i valori precedenti

non può essere usata quando possono esserci più valori per la stessa chiave

Page 35: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

35

HashMap Un requisito fondamentale per le mappe

la rapidità di inserimento e cancellazione

L’implementazione fondamentale

HashMap

di gran lunga la più veloce

La tecnica sottostante

tecnica di hashing ovvero basata su “funzioni di hashing”

HashMap Funzione di hash

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

Caratteristica tipica di una funzione hash

l’hash deve essere calcolabile rapidamente

Classificazione delle funzioni hash

funzioni con collisioni o prive di collisioni

Funzione priva di collisione

non ci sono due valori per cui l’hash è uguale

possibile solo se i valori sono finiti

Funzione con collisione

più valori possono avere lo stesso valore di hash

caso tipico

Page 36: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

36

HashMap Implementazione 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 – 1

in questo modo si ottiene un indice nell’array; la coppia <chiave, riferimento> viene aggiunta in coda al bucket della posizione ottenuta

Page 37: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

37

HashMap Implementazione 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 chiave se viene trovata una chiave identica a quella cercata, viene restituito il

riferimento altrimenti viene restituito null Due operazioni fondamentali il calcolo della funzione di hash il confronto tra le chiavi Calcolo della funzione di hash viene usato il metodo hashCode() ereditato da Object Confronto tra le chiavi viene utilizzato il metodo equals() ereditato da Object

HashMap Nota

le implementazioni standard sono basate sull’indirizzo in memoria

potrebbero non essere quelle adatte a fare hashing in alcuni casi

Nelle classi principali della piattaforma

sono 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()

Page 38: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

38

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

Capacity: 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.

Insiemi Altre classi significative delle collezioni

interface java.util.Set: rappresenta una collezione non ordinata e priva di duplicati

due principali implementazioni: HashSet e TreeSet

interface 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 liste

in alcuni casi sono più naturali

Esempio: Gestione Appuntamenti

potrei utilizzare un oggetto di tipo java.util.Set per rappresentare l’insieme dei partecipanti ad una Riunione

Page 39: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

39

Insiemi A questo punto possiamo vedere come scandire una mappa

due metodi principali

ottengo l’insieme delle chiavi con Set keySet() e scandisco l’insieme con un iteratore e prelevo dalla mappa tutti gli elementi

ottengo 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 implementazioni

Infatti

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

Ordinamenti In 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 particolare per ordinare una collezione di riferimenti, gli oggetti relativi devono essere

confrontabili rispetto ad una precisa relazione di ordine Esempio la lista degli Impegni un ordinamento possibile: per orario un altro ordinamento: in ordine alfabetico rispetto alla descrizione un altro ordinamento ancora: rispetto al luogo di svolgimento per poter ordinare una lista di impegnibisogna decidere il criterio di

ordinamento

Page 40: STRUTTURE DATI IN JAVA - diit.unict.it · Package java.util STRUTTURE DATI IN JAVA ... i resizable array sono liste di array i balanced tree sono alberi realizzati con puntatori le

40

In Java

gli oggetti ordinabili devono implementare l’interfaccia java.lang.Comparable

java.lang.Comparable

prevede un unico metodo

int compareTo(Object o)

risultato > 0 se this segue o nell’ordinamento

risultato < 0 se this precede o nell’ordinam.

risultato = 0 se this non precede nè segue o

Ordinamenti Nota

l’utilizzo di Comparable prevede che sia possibile cambiare il codice delle classi che definiscono gli oggetti da ordinare

per implementare Comparable e definire compareTo()

se questo non è possibile, è possibile utilizzare un approccio alternativo

utilizzare un oggetto esterno comparatore

L’interfaccia java.util.Comparator

unico metodo: int compare(Object o1, Object o2)

gli oggetti che implementano l’interfaccia sono quindi capaci di confrontare oggetti secondo algoritmi specifici