Parti II e III 1 Framework Collections in Java: API Java http://java.sun.com/ Generics in Java Tutorial Sun (in inglese) http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf Testo di Riferimento (usato nei corsi precedenti) Horstmann - Concetti di informatica e fondamenti di Java – Apogeo 2 Collection Framework (contd …) 3 Data la porzione di codice static int segreto(ArrayList a) { int r = ((Integer) a.get(0)).intValue(); Iterator i = a.iterator(); while (i.hasNext()) { int c=((Integer)i.next()).intValue(); if (c<r) r=c; } return(r); } Con input ArrayList a = new ArrayList();a.add(3);a.add(5); A) il metodo calcola la somma dei valori B) il metodo calcola il minimo dei valori del vettore C) il metodo calcola il massimo dei valori del vettore D) il metodo genera una eccezione in esecuzione Data la porzione di codice static boolean segreto2(Iterator i) { int prec = ((Integer) i.next()); while (i.hasNext()) { int c=((Integer)i.next()).intValue(); if (prec>c) return false; } return(true); } Con input ArrayList a = new ArrayList(); a.add(“3”); a.add(“5”); segreto2(a.iterator()) A) il metodo genera una eccezione in esecuzione B) il metodo calcola il massimo dei valori del vettore C) il metodo ritorna vero se la sequenza di valori è crescente D) il metodo ritorna vero se la sequenza di valori è decrescente Data la porzione di codice static void segreto3(ArrayList a, Object v) { for (int i = a.size(); i < a.size()+10; i++) { final Object valore = a.get(i); if (valore == null) a.set(i, v); } } A) il metodo sostituisce gli elementi nulli del vettore con v B) il metodo genera una eccezione di cast in esecuzione C) il metodo genera una eccezione di “index out of bound” in esecuzione D) il metodo stampa i valori del vettore B – A - C 7 In stazione c’e’ un treno passeggeri pronto a partire. Due amici devono prendere il treno ma non vogliono viaggiare in piedi; chiedono allora al capotreno se ci sono posti a sedere e gli viene risposto che ce n’è rimasto uno solo in tutto il treno. I due amici decidono allora di salire uno in testa e uno in coda e procedendo alla stessa velocità vanno alla ricerca del vagone in cui si trova il posto libero: il primo che lo trova si siederà. Rappresentando il treno come una lista di interi che indicano i posti rimasti liberi in ciascun vagone, scrivere una funzione in grado di dire quale dei due amici si siederà (quello salito in testa o quello salito in coda) static int trovaPosto(ArrayList treno) Ritorna 1 se si siede l’amico salito in testa, 2 se quello salito in cosa e 0 se arrivano insieme al vagone con l’unico posto libero 0 0 0 0 0 0 1 0 0 0 static int trovaPosto(ArrayList treno) { boolean trovato = false; int i = 0; do { Integer postiLiberi = (Integer) treno.get(i); if (postiLiberi.intValue() > 0) { trovato = true; } else i++; } while (!trovato && i < treno.size()); if (!trovato) return -1; if (i<treno.size()/2)return 1; else if (i>treno.size()/2)return 2; else return 0; } 9 I Generics 10 Le liste e gli insiemi sono collezioni di variabili Object Ogni volta che si vuole accedere agli elementi occorre fare il cast ArrayList a=new ArrayList(); a.add(“una stringa”); String s=(String) a.get(0); Ad una stessa collezione posso aggiungere elementi di tipi differenti non posso specificare che sono ammessi solo oggetti di un certo tipo ArrayList a=new ArrayList(); a.add(new Integer(10)); a.add(“una stringa”); Si possono definire collezioni di tipi particolari? Esempio: lista di Point, insieme di Studente, ecc. 11 Si può specificare che una lista contiene solo elementi di un certo tipo: LinkedList<Studente> l = new LinkedList<Studente>(); Una volta fatto questo, è come se la lista fosse una sequenza di variabili Studente, invece che una lista di variabili Object: si possono solo inserire oggetti Studente (o sottoclassi): l.add(new Point(20,30)); è un errore; il valore di ritorno di get è di tipo Studente Cosa cambia si mette <Tipo> nella dichiarazione di variabile e nel costruttore; al posto di Object, si usa sempre Tipo in tutti i metodi (get, add, ecc.) 12 Definire una Lista di studenti: import java.util.*; class ListStud { public static void main(String args[]) { LinkedList<Studente> l; l=new LinkedList<Studente>(); l.add(new Studente("Ciccio", 932222)); l.add(new Studente("Franco", 234325)); // errore // l.add(new Point(20,30)); Studente s=l.get(1); } } 13 Introduzione Programmazione generica: creazione di costrutti di programmazione che possano essere utilizzati con tipi di dati diversi. In Java si può raggiungere l’obiettivo della programmazione generica usando l’ereditarietà oppure le variabili di tipo. Esempio: ArrayList di Java ArrayList<String> Classe generica: è stata dichiarata usando una variabile di tipo E. La variabile di tipo rappresenta il tipo degli elementi: public class ArrayList<E> // si può usare "ElementType" invece di E { public ArrayList() { . . . } public void add(E element) { . . . } . . . } 14 Creazione di variabili di classi generiche Le variabili di tipo possono essere sostituite, all’atto della creazione di esemplari, con nomi di classe o di interfacce ArrayList<String> ArrayList<MyClass> Non si può usare come sostituto uno degli otto tipi di dati primitivi ArrayList<double> // Sbagliato! Usate un esemplare di ArrayList<Double> Esempi: ArrayList<String> a = new ArrayList<String>(); LinkedList<String> b = new LinkedList<String>(); 15 I metodi delle classi generiche Il tipo di dato che indicate va a sostituire la variabile di tipo utilizzata nella definizione dell’interfaccia o della classe generica Esempio: nel metodo add di un oggetto di tipo ArrayList<String> la variabile di tipo E viene sostituita dal tipo String public void add(String element) public String get(int index) Esempi: ArrayList<String> a =new ArrayList<String>(); String s=a.get(0);//no cast Iterator<String>=a.iterator(); //ritorna un iterator generico a.add(“paperino”);//non posso usare tipi differenti da String 16 Caratteristiche delle classi generiche Le variabili di tipo rendono più sicuro e di più facile comprensione il codice generico. E’ impossibile aggiungere un oggetto di tipo Integer ad un esemplare di ArrayList<String> È invece possibile aggiungere un oggetto di tipo Integer ad un esemplare di ArrayList (senza generics) che sia stato creato con l’intenzione di usarlo per contenere stringhe Tutte le classi del JCF sono generiche Collection<E>, Set<E>, List<E> … ArrayList<E>, LinkedList<E> … Iterator<E> … 17 Esempi di utilizzo ArrayList<String> a1 = new ArrayList<String>(); Integer numero=new Integer(30); // Dovrebbe contenere oggetti di tipo String LinkedList a2 = new LinkedList(); // errore di compilazione a1.add(numero); // errore non individuato dal compilatore a2.add(numero); //errore di esecuzione String account = (String) a2.get(0); 18 ArrayList<E> boolean add(E e) void add(int index, E element) E get(int index) E set(int index, E element) void clear() Iterator<E> iterator() int size() Iterator<E> boolean hasNext() E next() void remove() 19 Scrivere un metodo java int somma(ArrayList<Integer> a) che somma gli elementi del vettore di interi. 5 3 4 8 2 Somma: 22 Tempo 5 minuti … 20 public static int somma(ArrayList<Integer> a){ int somma=0; for (int i=0;i<a.size();i++){ Integer elem=a.get(i) somma=somma+elem.intValue(); } return somma; } Per esercizio: implementare il metodo somma utilizzando gli iteratori 21 Collection<E>: List<E> ArrayList<E> LinkedList<E> Vector<E> Set<E> SortedSet<E> TreeSet<E> HashSet<E> LinkedHashSet<E> Altre interfacce disponibili Queue<E>,Dequeue<E>,Stack<E>, Map<K,V>, SortedMap<K,V> … 22 PARTE 1: Confrontare il codice delle varie implementazioni del metodo somma ed evidenziarne le differenze PARTE 2: Scrivere un metodo Java che dato un ArrayList<String> di stringhe restituisca una unica stringa che e’ la concatenazione di tutti i suoi elementi. 23 Scrivere il metodo Java void inverte(ArrayList<Integer> a) che prende un ArrayList<Integer> e ne inverte l’ordine degli elementi L’elemento in posizione “i” va scambiato con quello in posizione “n-i-1” 1 2 3 4 5 5 4 3 2 1 Scrivere il metodo Java ArrayList<Integer> duplica(Integer v, int n) che prende un valore v e un numero n e ritorna un ArrayList<Integer> contenente n elementi di valore v 24 Data la porzione di codice: ArrayList<String> s=new ArrayList<String>(); a.add(new Integer(10)); ArrayList p=new ArrayList (); p.add(new Integer(10)); Indicare quali, tra le istruzioni seguenti, genera un errore in compilazione o in esecuzione (eccezione): 1. s.add(“paperino”); 2. s.add(new Integer(10)); 3. String q=s.get(0); 4. Object o=s.get(0); 5. Integer i=s.get(0); 6. s.add(s.get(0)); 7. p.add(“paperino”); 8. p.add(new Integer(10)); 9. String q=p.get(0); 10. Object o=p.get(0); 11. Integer i=p.get(0); 12. p.add(p.get(0)); Verificare le risposte al calcolatore 25 Comparable Si può ordinare un array di Object? No, perchè non esiste un ordinamento per tutti gli oggetti Per ordinare un insieme di oggetti, deve esistere una funzione di confronto di questi oggetti Interfaccia predefinita Comparable: rappresenta tutti gli oggetti sui quali è definito un ordinamento totale 27 interface Comparable<T> { public int compareTo(T o); } interface Comparable { public int compareTo(Oject o); } Se una classe implementa Comparable, allora ha un metodo compareTo(T o) Quando si definisce una classe, il metodo compareTo viene implementato in modo tale che a.compareTo(b) ritorna: un valore minore di zero se a è minore di b uguale a zero se a è uguale a b un valore maggiore di zero se a è maggiore di b 28 La definizione del metodo compareTo è semplicemente che si tratta di un metodo che ha un Object come argomento e ritorna un int Il fatto che a.compareTo(b) dice se a è minore, uguale o maggiore di b è una convenzione Non c'è nessun vincolo sintattico che ci obbliga a implementare compareTo come il confronto: class Strana implements Comparable<Strana> { public int compareTo(Strana o) { return (int) Math.random()*2-1; } } È un errore semantico/concettuale Effetto di un errore del genere: i metodi che lavorano su oggetti Comparable si comportano in modo anomalo Una cosa simile succede per equals 29 public static class Studente implements Comparable<Studente> { private String nome; private String cognome; public Studente(String nome, String cognome) { this.nome = nome; this.cognome = cognome; } public int compareTo(Studente o) { int compCognome=cognome.compareTo(o.cognome); if (compCognome != 0) return compCognome; else return nome.compareTo(o.nome); } public String getCognome() {return cognome;} public String getNome() {return nome;} } Esercizio per casa: ordinare gli studenti in ordine decrescente 30 Metodo che ordina un array di due elementi: static void ordina(Comparable c[]) { Comparable t; if(c[0].compareTo(c[1])<=0) return; t=c[0]; c[0]=c[1]; c[1]=t; } Esempio di programma: public static void main(String args[]) { Integer a[]=new Integer[2]; a[0]=new Integer(4); a[1]=new Integer(2); ordina(a); System.out.println(a[0]+" "+a[1]); } 31 Lo stesso metodo funziona per qualsiasi classe che implementa l'interfaccia Comparable String implementa Comparable L'ordinamento fra stringhe è quello lessicografico (detto anche alfabetico...) String b[]=new String[2]; b[0]="Ciccio"; b[1]="Bruno"; ordina(b); System.out.println(b[0]+" "+b[1]); Uso lo stesso metodo per le stringhe 32 Principali interfacce definite nel JCF Collection un multiinsieme non ordinato List una sequenza ordinata di elementi Set un insieme (non ordinato) di elementi SortedSet un insieme ordinato per compareTo Map un tabella (non trattata nel corso) 33 Differenza List e SortedSet List gli elementi sono in una sequenza qualsiasi SortedSet gli elementi sono ordinati secondo l'ordinamento specificato da compareTo Attenzione! Nell'interfaccia SortedSet non esiste il metodo get(int index) Gli iteratori di SortedSet scandiscono l'insieme in ordine crescente 34 Esempio: inserisco alcuni interi e poi li stampo: La classe TreeSet implementa l'interfaccia SortedSet public static void main(String args[]) { SortedSet<Integer> s=new TreeSet<Integer>(); s.add(new Integer(21)); s.add(new Integer(0)); s.add(new Integer(4)); Iterator i=s.iterator(); while(i.hasNext()) System.out.println(i.next()); } Viene stampato: 0 4 21 Gli iteratori scandiscono l'insieme in ordine L'ordinamento che is usa è quello dato da compareTo 35 Implementare il bubble sort di un vettore di elementi comparable void bubbleSort(ArrayList<Comparable> a) Suggerimenti: Utilizzare il metodo compareTo per confrontare gli elementi 36 public static void bubbleSort(ArrayList<Comparable> a) { int end = a.size() - 1; boolean scambio = true; while (scambio) { scambio = false; for (int i = 0; i < end; i++) { //a[i+1]<a[i] if (a.get(i + 1).compareTo(a.get(i)) < 0) { scambia(a, i, i + 1); scambio = true; } } //Ho gia' portato l'elemento //piu' pesante in fondo all'array end--; } } 37 private static void scambia (ArrayList<Comparable> a, int i, int j) { Comparable temp = a.get(i); a.set(i, a.get(j)); a.set(j, temp); } 38