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