Esercitazione su Vector. Permette di definire collezioni di dati generiche, che sono in grado di...

Post on 03-May-2015

216 views 2 download

Transcript of Esercitazione su Vector. Permette di definire collezioni di dati generiche, che sono in grado di...

Esercitazione su

Vector

Vector

• Permette di definire collezioni di dati generiche, che sonoin grado di memorizzare elementi di ogni sottotipo di Object

•Definito nella classe java.util.Vector

-memorizzano sequenze di oggetti di lunghezza variabile

-possono memorizzare oggetti di tipo diverso, purche’ sottotipi

di Object, (es. String, Integer etc.), anche tra loro non omogenei

Specifica (alcuni metodi)

public Vector (){\\EFFECTS: crea un vettore vuoto}

• Notate che a differenza che per gli arrays non e’ necessario fissare al momento della creazione la dimensione

• Ci sono anche altri costruttori tipo quelli degli arrays che permettono di creare un vettore vuoto ma con una certa capacita’ (dato numero di posizioni allocate ma vuote). Serve solo per avere implementazioni piu’ o meno efficienti (per ora lo ignoriamo)

public int size (){\\EFFECTS: restituisce il numero di elementi presenti nel

vettore}

public Object elementAt (int index){\\EFFECTS: restituisce l'elemento di indice index }

public void setElementAt (Object obj, int  index){\\EFFECTS:

sostituisce obj all'oggetto della posizione index}

• Se index e’ fuori dal size del vettore viene sollevata una eccezione come per gli arrays

Metodi simili a quelli dell’array

 public void insertElementAt (Object obj, int index){\\MODIFIES:this \\EFFECTS: inserisce obj nella posizione index e sposta tutti gli elementi, da index in poi, di una posizione}

public void addElement (Object obj){\\MODIFIES:this\\EFFECTS: aggiunge una posizione alla fine che contiene obj }

• La dimensione del Vector cambia, viene aggiunta una posizione

alla fine o in un dato punto

Metodi per aggiungere

 public void removeElementAt (int index){\\MODIFIES:this\\EFFECTS: rimuove l'oggetto presente nella posizione index e spostaall'indietro di una posizione tutti gli elementi successivia quello rimosso}public boolean removeElement (Object obj){\\MODIFIES:this\\EFFECTS: rimuove la prima occorrenza

dell'oggetto obj se presente restituendo true,oppure  restituisce false}

• La dimensione del Vector cambia, viene ricompattato (non rimane una posizione vuota)

Metodi per rimuovere

Esercizio Proposto

• Definire una classe VectorOp che definisce alcune procedure stand-alone (metodi statici) che operano su Vector contenenti Integer

• Il fatto che un Vector contenga Integer non e’ intrinseco nel tipo di dato (va messa una precondizione)

public class VectorOp{\\OVERVIEW: fornisce procedure stand-alone per manipolare Vectors di Integer

public static int min(Vector v){\\REQUIRES: v non e’ null e contiene Integer\\EFFECTS: restituisce il minimo di v, 0 se e’ vuoto

if (v.size()==0) {return 0;} int min=((Integer) v.elementAt(0)).intValue(); for (int i=1; i < v.size(); i++) {int x= ((Integer) v.elementAt(i)).intValue(); if (x < min) {min=x;} }return min;} NOTA: uso del Cast!

public static boolean search(Vector v,int x){\\REQUIRES: v non e’ null e contiene Integer\\EFFECTS: restituisce true se x appartiene a v, false altrimenti

for (int j=0; j < v.size(); j++){int y=((Integer) v.elementAt(j)).intValue(); if (x==y) {return true;}}return false;}

public static Vector inc(Vector v,int x){\\REQUIRES: v non e’ null e contiene Integer\\EFFECTS: restituisce il Vector ottenuto incrementando ogni elemento di x Vector nuovo=new Vector();for (int j=0; j < v.size(); j++){int y= ((Integer) v.elementAt(j)).intValue();nuovo.addElement(new Integer(y+x) );}return nuovo;}

public static Vector reverse(Vector v){\\REQUIRES: v non e’ null e contiene Integer\\EFFECTS: restituisce il Vector ottenuto invertendo gli elementi di v

Vector nuovo=new Vector();for (int j=v.size()-1; j >=0; j--){nuovo.addElement( v.elementAt(j) );} \\ cast non necessarioreturn nuovo;}

public static void remove(Vector v,int x){\\REQUIRES: v non e’ null e contiene Integer\\MODIFIES: v\\EFFECTS: elimina tutte le occorrenze di x in vfor (int j=0; j < v.size(); j++){int y= ((Integer) v.elementAt(j)).intValue();if (y==x)v.removeElementAt(j );}}

public static Vector sort(Vector v){\\REQUIRES: v non e’ null e contiene Integer\\EFFECTS: restituisce il Vector ottenuto mettendo gli elementi di v in ordine\\ crescenteVector nuovo=new Vector(); \\ vettore che viene mantenuto ordinatoif (v.size()==0) {return nuovo;}

for (int i=0; i< v.size();i++){int y=((Integer) v.elementAt(i)).intValue(); \\ elemento di v da inserireboolean trovato=false;int j=0;while (j < nuovo.size() && !trovato) \\ scorre nuovo cercando il punto giusto{int w=((Integer) nuovo.elementAt(j)).intValue();if (w >= y) {nuovo.insertElementAt(new Integer(y),j); trovato=true;}else j++;}if (! trovato){nuovo.addElement(new Integer(y));}}return nuovo;}

Commenti

• Quando usare Vector o Array?

• Array piu’ efficienti

• Vector utile quando bisogna implementare

strutture dati di lunghezza variabile

• Esempio: pila (Stack) di interi

• Mantiene gli elementi per ordine di inserimento (LIFO)

Quali operazioni?

• isEmpty() serve per testare se la pila e’ vuota

• top() serve per leggere l’elemento al top della pila, ovvero l’ultimo inserito

• pop() rimuove l’ultimo elemento inserito (al top della pila)

• push (int x) inserisce x nella pila al top

Specifica (INTERFACCIA PUBBLICA)

public class Stack {

\\ OVERVIEW: uno Stack e’ una collezione di interi organizzati per ordine di inserimento con una politica LIFO. E’ modificabile

public Stack () {

\\ EFFECTS: costruisce uno Stack Vuoto}public boolean isEmpty() {

\\ EFFECTS: se this e’ vuoto restituisce true, altrimenti false}

public int top() {

\\ REQUIRES: this non e’ vuoto\\ EFFECTS: restituisce l’ultimo elemento inserito }

NOTA: specifica parziale (eccezioni?)

Modificatori

public void pop() {

\\ REQUIRES: this non e’ vuoto\\ MODIFIES: this\\ EFFECTS: se this non e’ vuoto rimuove l’ultimo elemento inserito}

public void push (int x) {

\\ MODIFIES: this\\ EFFECTS: inserisce x nella pila (al top)}

Implementazione

• Rappresentazione: usiamo un Vector per implementare la pila, l’ultimo elemento inserito e’ l’ultimo elemento (top della pila)

• Chiaramente dovremo usare un Vector di Integer

• Implementiamo i metodi di conseguenza

• Nota: l’implementazione deve essere nascosta (usiamo variabili private)

Implementazione

public class Stack {

\\ OVERVIEW: uno Stack e’ una collezione di interi organizzati per ordine di inserimento con una politica LIFO. E’ modificabile

private Vector pila; \\rappresentazione privata public Stack () {

\\ EFFECTS: costruisce uno Stack vuotopila=new Vector();}

public boolean isEmpty() {

\\ EFFECTS: se this e’ vuoto restituisce true, altrimenti falseif (pila.size()==0) {return true;}; return false;}

public int top() {\\REQUIRES: this non e’ vuoto

\\ EFFECTS: restituisce l’ultimo elemento inseritoInteger x=pila.elementAt(pila.size()-1));return x.intValue();

}public void pop() {{\\REQUIRES: this non e’ vuoto

\\ MODIFIES: this\\ EFFECTS: rimuove l’ultimo elemento inserito pila.removeElementAt(pila.size()-1));}

public void push (int x) {

\\ MODIFIES: this\\ EFFECTS: inserisce x nella pilapila.addElement(new Integer(x));}}

Interfaccia Pubblica

• Ricordiamo che: tutto il codice che usa Stack deve essere scritto usando solo interfaccia pubblica (non vede che e’ implementata con un Vector)

• Esempio: procedura stand-alone che rimpiazza gli ultimi due elementi inseriti con la loro somma

public static void sum (Stack p) {\\REQUIRES: p contiene almeno due elementi\\MODIFIES: p\\EFFECTS: rimpiazza gli ultimi due elementi inseriti in p con la loro somma

int primo, secondo;primo = p.top();p.pop();secondo = p.top();p.pop();p.push(primo+secondo);}

Notate che non accede alla variabile pila di tipo Vector, usa solo l’interfacciapubblica!

Commenti

• Sarebbe piu’ facile scrivere il codice accedendo direttamente alla rappresentazione del tipo di dato, e.g.

private Vector pila; //la rappresentazione

ESEMPIOInteger primo, secondo;primo = (Integer) p.pila.elementAt(p.pila.size()-1);secondo= (Integer) p.pila. elementAt(p.pila.size()-2);p.pila.removeElementAt(p.pila.size()-1);p.pila.setElementAt(primo.intValue()+secondo.intValue(),p.pila.size(0-1);

Ma….

• Questo approccio e’ metodologicamente sbagliato

• Mantenere l’implementazione nascostapermette di-garantire proprieta’ del tipo di dato-rendere il codice che lo usa indipendente

dalla sua implementazione

Esempio

• Se il tipo di dato dovesse essere riprogettato(lo implemento p.e. con una lista concatenata

invece che con un Vector)• Tutto il codice scritto usando l’interfaccia

pubblica continuerebbe a funzionare• Al contrario se accedesse alla

rappresentazione dovrebbe essere riprogettato

Esercizio Proposto

• Definire una classe Abbonato i cui oggetti descrivono le informazioni relative ad un abbonato al telefono: nome (di tipo String ) e numero di telefono (int)

• Con i seguenti costruttori e metodi

public class Abbonato{

public Abbonato(String s,int n){

\\EFFECTS: crea un nuovo abbonato con nome s

\\ e numero n}

public String nome(){

\\EFFECTS: restituisce il nome di this}

public int numero(){

\\EFFECTS: restituisce il numero di this}

\\ metodo overridden

public boolean equals(Object o){

\\REQUIRES: o e’ di tipo Abbonato

\\EFFECTS: restituisce true se this ed o sono uguali}

}

}

•Definire una classe Elenco i cui elementi sono di tipo Abbonato

•Gli Abbonati sono mantenuti all’interno dell’Elenco in modo ordinato

rispetto al nome,

ESEMPIO: (Francesca, 2867) <= (Marco, 133)

•Inoltre i numeri di telefono nell’elenco sono tutti diversi

•Per Elenco vengono forniti metodi per

-cercare all’interno dell’elenco il numero di telefono a partire dal nome

- inserire un nuovo Abbonato

- rimuovere un Abbonato

- cambiare il numero di telefono

public class Elenco{

public Elenco(){

\\EFFECTS: crea un nuovo elenco vuoto}

public int cercanum(String s) {

\\EFFECTS: restituisce il numero di telefono del primo abbonato

presente in this che ha nome s, altrimenti restituisce 0}

public void inserisci(String s){ \\MODIFIES: this \\EFFECTS: aggiunge un nuovo Abbonato all’elenco (this) con nome s e con un nuovo numero di telefono}

public void rimuovi(String s){ \\MODIFIES: this \\EFFECTS: rimuove dall’elenco (this) tutti gli abbonati con nome s}

public int cambia(String s, int x){ \\MODIFIES: this \\EFFECTS: se nell’elenco compare l’abbonato (s,x), rimpiazza il numero x con un nuovo numero di telefono y e lo restituisce}

public String toString(){\\EFFECTS: restituisce una stringa che contiene la sequenza di \\abbonati di this}

}

Implementazione: suggerimenti

Nella classe Elenco usare

• una variabile statica per memorizzare il primo numero di telefono disponibile (inizializzata inizialmente ad 1), tipo come abbiamo fatto in classe per gestire il numero di matricola

• una variabile d’istanza di tipo Vector per memorizzare gli abbonati

(sfruttando il fatto che Abbonato e’ sottotipo di Object)

• Attenzione: l’ordinamento va mantenuto (il Vector e’ ordinato) e sfruttato (p.e. per la ricerca)

Al solito

• In parallelo il testing delle due classi

• Usa solo l’interfaccia pubblica