Ripasso di Java A.A. 16/17 DA1 – A. Pietracaprina 1 1 Programma Stand-alone File: MyProgram.java import … ; // import a package or a class public class MyProgram { public static void main(String[] args) { …….. // corpo del metodo main } /* eventuali altri metodi */ } A.A. 16/17 DA1 – A. Pietracaprina 2 2 Programma stand-alone Compilazione: javac MyProgram.java Crea un bytecode MyProgram.class eseguibile sulla Java Virtual Machine (JVM) Esecuzione: java MyProgram Oss. Richiede che la directory corrente sia nel CLASSPATH. Altrimenti usiamo: java –cp . MyProgram Oss. In alternativa si può usare un Integrated Development Environment (IDE), ad es. Eclipse, JBuilder A.A. 16/17 DA1 – A. Pietracaprina 3 3 Esempio Calcolo dell’n-esimo numero di Fibonacci F(n) Def. successione di Fibonacci: F(0)=0, F(1)=1, F(n)=F(n-2)+F(n-1) se n≥2, n intero File: Fibonacci.java Input: n intero ≥ 0 Output: F(n) A.A. 16/17 DA1 – A. Pietracaprina 4 4 Esempio: calcolo dell’n-esimo numero di Fibonacci import java.util.Scanner; public class Fibonacci{ public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Which Fibonacci number do you want?"); int n = input.nextInt(); //compute F(n) with iterFibonacci and measure running time System.out.println("\nLet's start the iterative algorithm!"); long time1 = System.currentTimeMillis(); long f = iterFibonacci(n); long time2 = System.currentTimeMillis(); System.out.println("F(n)="+f); System.out.println("Time of iterFibonacci="+(time2-time1)); } A.A. 16/17 DA1 – A. Pietracaprina 5 5 Esempio: calcolo dell’n-esimo numero di Fibonacci System.in: variabile statica (classe System) di tipo InputStream associata alla “standard input device” (default: tastiera con echo su Java console) System.out: variabile statica (classe System) di tipo PrintStream associata alla “standard output device” (default: Java console) Scanner: classe che permette di leggere un oggetto di tipo InputStream (ad es., System.in) dividendolo in token separati da delimitatori (ad es., spazi, tab, newline). I token possono essere trasformati in tipi diversi utilizzando il metodo nextType() (ad es., nextInt()). I metodi nativi di System.in che derivano dalla classe InputStream sono di più basso livello (ad es., lettura di byte) currentTimeMillis(): metodo statico della classe System che restituisce il tempo dal 1/1/1970 misurato in millisecondi A.A. 16/17 DA1 – A. Pietracaprina 6 6 Esempio: calcolo dell’n-esimo numero di Fibonacci /*Iterative algorithm*/ public static long iterFibonacci(int n){ if(n<=1) return n; long x=0; long y=1; long tmp; for(int i=2; i<=n; i++){ tmp = x; x = y; y = tmp+x; //At the end of the ith iteration, x=F(i-1) and y=F(i) } return y; } } // end of class Fibonacci A.A. 16/17 DA1 – A. Pietracaprina 7 7 Esercizi Esercizi 1. Implementare l’algoritmo ricorsivo per il calcolo dell’n-esimo numero di Fibonacci, e confrontarne le prestazioni con quelle dell’algoritmo iterativo. 2. Implementare findBrute e findKMP confrontandone le prestazioni A.A. 16/17 DA1 – A. Pietracaprina 8 8 Caratteristiche Java e approccio Object Oriented Portabilità: • Java Virtual Machine (JVM): macchina virtuale che fornisce un modo platform-independent di eseguire il codice. E’ implementata su tutte le principali piattaforme (Hw+S.O.) MyClass.java → MyClass.class (bytecode) • Range dei tipi base definiti dal linguaggio • int → 32 bit, long → 64 bit • float → 32 bit, double → 64 bit • char → 16 bit (Unicode) • Tutti i tipi base (tranne boolean e void) sono con segno. A.A. 16/17 DA1 – A. Pietracaprina 9 9 Caratteristiche Java e approccio O.O. Modularità: • Applicazione ≡ insieme di oggetti interagenti • Un oggetto è un’istanza di una classe che definisce Variabili di istanza (instance variables o fields) Metodi (methods) La classe rappresenta il “tipo” dell’oggetto Integer i = new Integer(5); Creazione di un oggetto di tipo Integer Definizione della variabile i di tipo Integer A.A. 16/17 DA1 – A. Pietracaprina 10 10 Caratteristiche Java e approccio O.O. Robustezza: • Funzionalità suddivise in componenti logiche Adattabilità: • Modifiche apportabili a singole componenti senza dover intaccare tutto il codice Riusabilità: • Singole componenti possono essere riutilizzate da altre applicazioni A.A. 16/17 DA1 – A. Pietracaprina 11 11 Caratteristiche Java e approccio O.O. Astrazione e Incapsulamento (Information Hiding): • Si astrae la specifica delle funzionalità, separandola dalla loro implementazione • Uso delle funzionalità solo in base alla specifica • L’implementazione delle funzionalità è nascosta • Gli errori sono più confinati (-> robustezza) • Possibilità di cambiare l’implementazione senza cambiare la specifica (-> adattabilità) • Nel caso delle strutture dati, questo approccio dà origine alla nozione di Abstract Data Type (ADT) A.A. 16/17 DA1 – A. Pietracaprina 12 12 Caratteristiche Java e approccio O.O. Abstract Data Type • Modello di struttura dati che specifica: il tipo di dati; le operazioni disponibili per accedere a essi e modificarli; e i parametri usati da tali operazioni. • In Java si realizza tramite interfacce (e, in parte, classi astratte) che contengono solo dichiarazioni di costanti e di metodi senza corpo A.A. 16/17 DA1 – A. Pietracaprina 13 13 Caratteristiche Java e approccio O.O. INTERFACCIA public interface A { public int a1(); public boolean a2(); } public class X implements A { public int a1() {…} public boolean a2() {…} public void b() {…} } … A var1 = new A(); NO! A var1 = new X(); OK! A.A. 16/17 DA1 – A. Pietracaprina A implements X Ad es., java.lang.String implements java.lang.Comparable 14 14 Caratteristiche Java e approccio O.O. CLASSE ASTRATTA • • Una classe che contiene definizioni (come una classe normale) e dichiarazioni (come un interfaccia) Non si possono istanziare oggetti da classi astratte! public abstract class A { public abstract int a1(); //no impl. public boolean a2(){…} //impl. } public class X extends A { public int a1() {…} //impl. metodo abst. public void b() {…} } … A var1 = new A(); NO! A var1 = new X(); OK! A.A. 16/17 DA1 – A. Pietracaprina A extends X Ad es., java.lang.Integer extends java.lang.Number 15 15 Caratteristiche Java e approccio O.O. Ereditarietà (Inheritance) • Si importano in una classe le caratteristiche di un’altra classe aggiungendone di nuove e/o specializzandone alcune • In Java: extends (subclass → superclass) public class S { public void a() {…} public void b() {…} public int c() {…} } public class T extends S { /* inherits b() and c() */ float y; public void a() {…} public boolean d() {…} } A.A. 16/17 S Superclass extends // added // specialized // added T Subclass Ogni classe estende implicitamente java.lang.Object DA1 – A. Pietracaprina 16 16 Caratteristiche Java e approccio O.O. Esempi S extends T cast A.A. 16/17 S var = new S(); … var.a(); // metodo di S var.b(); // metodo di S var.d(); // ERRORE! (var è dichiarata di tipo S) ((T) var).d(); // ERRORE (var è definita di tipo S) /* var dichiarata di tipo S e definita di tipo T */ S var = new T(); … var.a(); // metodo di T (polimorfismo) var.b(); // metodo di S var.d(); // ERRORE! (var è di tipo S) ((T) var).d(); // metodo di T DA1 – A. Pietracaprina 17 17 Caratteristiche Java e approccio O.O. Overloading e Polimorfismo • Signature di un metodo: nome del metodo + numero e tipo dei parametri (in ordine da sx verso dx). Il nome dei parametri e il tipo di ritorno non importano. • Overloading: possibilità di avere due metodi nella stessa classe o nella stessa gerarchia di classi che hanno lo stesso nome ma signature diverse. Ad es. a(); a(int x, float y); • Polimorfismo (overriding): possibilità di avere due metodi con la stessa signature all’interno della stessa gerarchia (in classi diverse). I metodi devono avere lo stesso return type. Ad es. metodo void a() in S e T nell’esempio. A.A. 16/17 DA1 – A. Pietracaprina 18 18 Caratteristiche Java e approccio O.O. Ereditarietà multipla per interfacce (non per classi!) public interface A {…} public interface B {…} public interface C extends A, B {…} A B extends extends C public class D implements A, B { // deve implementare tutti I metodi di A e B } public class D implements C { // deve implementare tutti i metodi di A e B // e quelli (eventuali) aggiuntivi di C } A.A. 16/17 DA1 – A. Pietracaprina 19 19 Programmazione Generica (generics) • È un tipo di polimorfismo, introdotto da Java 1.5.0. Permette l’uso di variabili di tipo nella definizione di classi, interfacce e metodi. Si parla in questo caso di classi/interfacce generiche e metodi generici. • Nel creare un’istanza di una classe generica si specifica il tipo (actual type) da sostituire con la variabile di tipo. L’actual type non può essere un tipo primitivo (ad es., int) ma deve essere una classe che estende Object • Nell’invocazione di un metodo generico la sostituzione della variabile di tipo con un actual type è fatta automaticamente in base ai parametri passati. • L’uso delle classi/interfacce generiche evita il ricorso a parametri di tipo “Object” e l’uso frequente di cast. A.A. 16/17 DA1 – A. Pietracaprina 20 20 Programmazione generica Esempio: classe generica public class MyClass<E> { E var1; // E indica un tipo qualsiasi (tranne i tipi base) E a() {…} void b(E param1) { var1 = param1; //OK! E s = new E(); //NO! il compilatore segnala un errore }} …. MyClass<Integer> x = new MyClass<Integer>(); // istanza /* la seguente classe permette di usare al posto di E solo estensioni della classe/interfaccia S */ public class MyClass1<E extends S> {…} A.A. 16/17 DA1 – A. Pietracaprina 21 21 Programmazione generica Esempio: metodo generico /* definizione */ public static <E> void myMethod (E param){…} N.B. la specifica del tipo generico deve comparire dopo i modificatori (ad es. public e static) e prima del tipo di ritorno /* invocazione */ myMethod (x); // E sostituito automaticamente con il tipo di x A.A. 16/17 DA1 – A. Pietracaprina 22 22 Esempio Completo LISTA: collezione di elementi organizzati secondo un ordine lineare tale per cui è identificabile il primo elemento, il secondo, … , e l’ultimo. Un elemento può essere acceduto tramite • position = nodo contenente l’elemento • index = intero ≥ 0 che indica il numero di elementi che precedono quello considerato X Y position A.A. 16/17 Z elemento DA1 – A. Pietracaprina index(Y) = 1 23 23 Esempio completo: lista Implementazione che privilegia l’accesso tramite position Position<E> usa PositionList<E> implements DNode<E> usa INTERFACCE implements NodePositionList<E> CLASSI Position: ADT che rappresenta il concetto di “nodo” PositionList: ADT che rappresenta il concetto di lista con accesso tramite posizione DNode: implementa Position come nodo di una lista doubly linked NodePositionList: implementa PositionList tramite DNode E: variabile di tipo che rappresenta il tipo degli elementi A.A. 16/17 DA1 – A. Pietracaprina 24 24 Esempio completo: lista Interfaccia Position<E> (file Position.java) public interface Position<E> { /** Return the element stored at this position */ public E element(); } A.A. 16/17 DA1 – A. Pietracaprina 25 25 Esempio completo: lista Interfaccia PositionList<E> (file PositionList.java) public interface PositionList<E> { /** Returns the number of elements in this list. */ public int size(); /** Returns whether the list is empty. */ public boolean isEmpty(); /** Returns the first node in the list. */ public Position<E> first(); /** Returns the last node in the list. */ public Position<E> last(); /** Returns the node after a given node in the list. */ public Position<E> after(Position<E> p); /** Returns the node before a given node in the list. */ public Position<E> before(Position<E> p); …. A.A. 16/17 DA1 – A. Pietracaprina 26 26 Esempio completo: lista Interfaccia PositionList<E>… …. /** Inserts an element at the front of the list. */ public void addFirst(E e); /** Inserts and element at the back of the list. */ public void addLast(E e); /** Inserts an element after the given node in the list. */ public void addAfter(Position<E> p, E e); /** Inserts an element before the given node in the list. */ public void addBefore(Position<E> p, E e); /** Removes a node from the list, returning the element stored there. */ public E remove(Position<E> p); /** Replaces the element stored at the given node, returning old element. */ public E set(Position<E> p, E e); } A.A. 16/17 DA1 – A. Pietracaprina 27 27 Esempio completo: lista Classe DNode<E> (file DNode.java): implementazione di Position<E> Elemento di tipo E x prev y next z DNode<E> A.A. 16/17 DA1 – A. Pietracaprina 28 28 Esempio completo: lista public class DNode<E> implements Position<E> { private DNode<E> prev, next; // References to the nodes before and after private E element; // Element stored in this position /** Constructor */ public DNode(DNode<E> newPrev, DNode<E> newNext, E elem) { prev = newPrev; next = newNext; element = elem; } public E element() { return element; } // Method from interface Position // Accessor methods public DNode<E> getNext() { return next; } public DNode<E> getPrev() { return prev; } // Update methods public void setNext(DNode<E> newNext) { next = newNext; } public void setPrev(DNode<E> newPrev) { prev = newPrev; } public void setElement(E newElement) { element = newElement; } } A.A. 16/17 DA1 – A. Pietracaprina 29 29 Esempio completo: lista Classe NodePositionList<E> (file NodePositionList.java): implementazione di PositionList<E> header trailer DNode con elementi Sentinelle A.A. 16/17 DA1 – A. Pietracaprina 30 30 Esempio completo: lista Classe NodePositionList<E> … public class NodePositionList<E> implements PositionList<E> { protected int numElts; // Number of elements in the list protected DNode<E> header, trailer; // Special sentinels /** Constructor that creates an empty list; O(1) time */ public NodePositionList() { numElts = 0; header = new DNode<E>(null, null, null); // create header trailer = new DNode<E>(header, null, null); // create trailer header.setNext(trailer); // make header and trailer point to each other } /** Returns the number of elements in the list; O(1) time */ public int size() { return numElts; } /** Returns whether the list is empty; O(1) time */ public boolean isEmpty() { return (numElts == 0); } …. A.A. 16/17 DA1 – A. Pietracaprina 31 31 Esempio completo: lista Classe NodePositionList<E> … … /** Checks if position is valid for this list and converts it to DNode */ protected DNode<E> checkPosition(Position<E> p) {…} public Position<E> first() { return header.getNext(); } public Position<E> after(Position<E> p) { DNode<E> v = checkPosition(p); DNode<E> next = v.getNext(); return next; } public void addAfter(Position<E> p, E element) { DNode<E> v = checkPosition(p); numElts++; DNode<E> newNode = new DNode<E>(v, v.getNext(), element); v.getNext().setPrev(newNode); v.setNext(newNode); } ... A.A. 16/17 DA1 – A. Pietracaprina 32 32 Programma di test: InsertionSort Position<E> PositionList<E> usa implements DNode<E> implements usa NodePositionList<E> usa Programma stand-alone Sort File: Position.java, PositionList.java, NodePositionList.java DNode.java, Sort.java Compilazione: javac Sort.java A.A. 16/17 DA1 – A. Pietracaprina 33 33 Esempio completo: InsertionSort Cosa possiamo ordinare? Solo oggetti che implementano l’interfaccia java.lang.Comparable<E>, perché contengono il metodo per confrontare: public int compareTo(E o) public interface Comparable<E> { public int compareTo(E o); } Ad es. la classe Integer implementa Comparable<Integer> x.compareTo(y): <0 se x<y =0 se x=y >0 se x>y A.A. 16/17 DA1 – A. Pietracaprina 34 34 Esempio completo: InsertionSort Classe Sort (file Sort.java) import java.util.*; public class Sort { public static void main(String[] args) { Scanner input = new Scanner(System.in); PositionList<Integer> L = new NodePositionList<Integer>(); System.out.print("Input number of ints to be sorted: "); int n = input.nextInt(); for (int i=0; i<n; i++) { System.out.print("Input next int: "); L.addFirst(new Integer(input.nextInt()));} sort(L); // call to sort method Position<Integer> p = L.first(); while (p != L.last()) { System.out.println(p.element().intValue()); p = L.after(p);} // end while System.out.println(p.element().intValue()); } A.A. 16/17 DA1 – A. Pietracaprina 35 35 Esempio completo: InsertionSort Classe Sort … public static <E extends Comparable<E>> void sort(PositionList<E> L) { if (L.size() <= 1) return; // L is already sorted in this case Position<E> pivot = L.after(L.first()); // pivot node Position<E> ins = L.first(); // insertion point while (true) { E x1 = pivot.element(), x2 = ins.element() ; while ((x1.compareTo(x2) < 0) && (ins != L.first())) { L.set(ins, x1); L.set(L.next(ins), x2); ins = L.prev(ins); x2 = ins.element(); } if (x1.compareTo(x2) < 0) { L.set(ins, x1); L.set(L.next(ins), x2); } if (pivot == L.last()) return; else { ins = pivot; pivot = L.after(pivot); } } // end while(true) } A.A. 16/17 DA1 – A. Pietracaprina 36 36 Esempio completo: InsertionSort Osservazioni • Le istruzioni che compaiono nella classe Sort dipendono solo dalla specifica delle interfacce Position e PositionList e non dalle loro implementazioni (DNode, NodePositionList). (Tuttavia NodePositionList compare nel «main» per poter inizializzare L.) • È quindi possibile cambiare l’implementazione delle classi DNode e NodePositionList senza dover cambiare la classe Sort, purché si mantenga la coerenza con le interfacce. • Il tipo degli oggetti da ordinare compare solo nel metodo «main» (per poter gestire input e output). Il resto del codice usa tipi generici A.A. 16/17 DA1 – A. Pietracaprina 37 37 Esempio completo: InsertionSort Versione alternativa di InsertionSort java.util.ArrayList<E> • Classe dell’API (Application Programming Interface) di java (Collection framework) • Implementa una lista (interfaccia java.util.List<E>) tramite array estendibile (extendable array), privilegiando l’accesso tramite index A.A. 16/17 DA1 – A. Pietracaprina 38 38 Esempio completo: lista Interfaccia List<E> public interface List<E> { /** Returns the number of elements in this list. */ public int size(); /** Returns whether the list is empty. */ public boolean isEmpty(); /** Inserts an element e to be at index i, shifting all elements after this. */ public void add(int i, E e); /** Returns the element at index i, without removing it. */ public E get(int i) /** Replaces the element at index i with e, returning the previous element at i. */ public E set(int i, E e) …. } A.A. 16/17 DA1 – A. Pietracaprina 39 39 Esempio completo: InsertionSort Schema delle classi List<E> implements ArrayList<E> usa Programma stand-alone A.A. 16/17 Sort DA1 – A. Pietracaprina 40 40 Esempio completo: InsertionSort Versione di InsertionSort che usa ArrayList import java.util.*; public class Sort { public static void main(String[] args) { Scanner input = new Scanner(System.in); List<Integer> L = new ArrayList<Integer>(); System.out.print("Input number of ints to be sorted: "); int n = input.nextInt(); for (int i=0; i<n; i++) { System.out.print("Input next int: "); L.add(i, new Integer(input.nextInt())); } sort(L); // call to sort method for (int i=0; i<n; i++) System.out.println(L.get(i)); } A.A. 16/17 DA1 – A. Pietracaprina 41 41 Esempio completo: InsertionSort Versione di InsertionSort che usa ArrayList … public static <E extends Comparable<E>> void sort(List<E> L) { if (L.size() <= 1) return; // L is already sorted in this case int i, pivot, ins, n=L.size(); for (pivot=1; pivot<n; pivot++) { ins = pivot-1; E x1 = L.get(pivot), x2 = L.get(ins); while ((ins >= 0) && (x1.compareTo(x2) < 0)) { L.set(ins, x1); L.set(ins+1, x2); ins--; if (ins >= 0) x2 = L.get(ins); } // end while } // end for } // end void sort } // end class Sort A.A. 16/17 DA1 – A. Pietracaprina 42 42 Collections • Collezione: un oggetto che raggruppa una molteplicità di elementi. • Collection framework (package java.util) contiene: Interfacce di varie collezioni Classi che implementano le interfacce Algoritmi (polimorfi) per operazioni su collezioni (es., ordinamento) Ampio uso della programmazione generica Collection Set HashSet Map List SortedSet ArrayList Queue LinkedList HashMap PriorityQueue extends TreeSet implements A.A. 16/17 DA1 – A. Pietracaprina SortedMap TreeMap Interfaccia Classe 43 43 Iteratori ITERATORI Iteratore: design pattern che permette di esaminare una collezione di oggetti, uno alla volta. Supporta le nozioni di /* In package java.util */ • Oggetto corrente (cursore) public interface Iterator<E> { public boolean hasNext(); • Prossimo oggetto public E Next(); } /* In package java.lang */ public interface Iterable<E> { public Iterator<E> iterator(); } A.A. 16/17 DA1 – A. Pietracaprina 44 44 Iteratori Esempio: implementazione di un iteratore in NodePositionList public interface PositionList<E> extends Iterable<E>{ … } ⇒ ogni classe che implementa PositionList dovrà includere il metodo iterator() A.A. 16/17 DA1 – A. Pietracaprina 45 45 Iteratori Classe che implementa l’interfaccia Iterator<E> public class ElementIterator<E> implements Iterator<E> { protected PositionList<E> list; // the underlying lst protected Position<E> cursor; // the next position /* Constructor*/ public ElementIterator(PositionList<E> L) { list = L; cursor = (list.isEmpty())? null : list.first(); } /* Methods from interface*/ public boolean hasNext() { return (cursor != null); } public E next() throws NoSuchElementException { if (cursor==null) throw new NoSuchElementException (“No such element”) E toReturn = cursor.element(); cursor = (cursor == list.last())? null : list.next(cursor); return toReturn; } } A.A. 16/17 DA1 – A. Pietracaprina 46 46 Iteratori Dentro la classe NodePositionList: public class NodePositionList<E> implements PositionList<E> { ….. public Iterator<E> iterator() { return new ElementIterator<E>(this); } } A.A. 16/17 DA1 – A. Pietracaprina 47 47 Riferimenti al testo ed esercizi Dal testo [GTG14] • Java: Capitoli 1 e 2 • Liste e iteratori: Capitolo 7 Esercizi • Scaricare dal sito del corso il codice di InsertionSort e testarlo su diverse tipologie di input (ad es., ordinato in senso crescente, ordinato in senso decrescente, random) A.A. 16/17 DA1 – A. Pietracaprina 48 48