Java. Classi Anonime In Java Da Java 1.1 si possono usare classi anonime per implementare interfacce. Espressioni Lambda. Implementazione Interfaccia

Documenti analoghi
18 - Vettori. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Java: Definire Classi e Creare Oggetti

Introduzione Generics Iteratori. Collezioni in Java. Dr. Giulio Pellitta. 13 aprile 2011

19 - Eccezioni. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

OCA JAVA 7 SE PROGRAMMER I DOCENTE: DOTT. FAUSTO DELL ANNO

Algoritmi di Ricerca. Esempi di programmi Java

Esempio su strutture dati dinamiche: ArrayList

Algoritmi di Ricerca. Esempi di programmi Java

OCA JAVA 8 SE PROGRAMMER I DOCENTE: DOTT. FAUSTO DELL ANNO

Programmazione. Cognome... Nome... Matricola... Prova scritta del 11 luglio 2014

Esempio su strutture dati dinamiche: ArrayList

public static boolean occorre (int[] a, int n) { int i = 0; boolean trovato = false;

STRUTTURE DATI: OLTRE GLI ARRAY LISTE

Programmazione Java Struttura di una classe, Costruttore, Riferimento this

Il problema è trovare un modo nel quale gli eventi dell oggetto di riferimento, siano comunicati a tutti gli altri interessati.

Metodi statici. Dichiarazione e chiamata di metodi statici

7 - Programmazione procedurale: Dichiarazione e chiamata di metodi ausiliari

Generics & Collections

Le basi del linguaggio Java

24 - Possibili approfondimenti

Il linguaggio Java: aggiunte in Java 1.5

Corso di Algoritmi e Strutture dati Programmazione Object- Oriented in Java (Parte I)

Esempio su strutture dati dinamiche: ArrayList

Programmazione. Cognome... Nome... Matricola... Prova scritta del 22 settembre Negli esercizi proposti si utilizzano le seguenti classi:

Corso di Linguaggi di Programmazione

Le basi del linguaggio Java

Programmazione orientata agli oggetti Classi astratte e interfacce

Programmazione a oggetti

Fondamenti di Informatica T2 Modulo 2. Corso di Laurea in Ingegneria Informatica Anno accademico 2008/2009. Enumerativi

Laboratorio di Programmazione Lezione 2. Cristian Del Fabbro

Notazione grafica UML

Classi astratte e progettazione OOP Esempio: l enciclopedia degli animali. Esempio Animali

Classi astratte e progettazione OOP Esempio: l enciclopedia degli animali. Esempio Animali

Programmazione a Oggetti e JAVA. Prof. B.Buttarazzi A.A. 2012/2013

Corso: Fondamenti di Informatica (Gruppo 2) a.a Corsi di laurea: Ing. Settore Informazione

Eccezioni Precisazioni e approfondimenti

Programmazione II Compitino (Vers. B)

IL LINGUAGGIO JAVA Input, Tipi Elementari e Istruzione Condizionale

Algebra di Boole: Concetti di base. E un algebra basata su tre operazioni logiche

INTRODUZIONE ALLA PROGRAMMAZIONE AD ALTO LIVELLO IL LINGUAGGIO JAVA. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica

18 - Classi parzialmente definite: Classi Astratte e Interfacce

GESTIONE DEGLI ERRORI

22 - Strutture Dati (Java Collections Framework)

Esonero di Informatica I. Ingegneria Medica

Capitolo 9. Tipi enumerativi, tipi generici e interfacce. c 2005 Pearson Education Italia Capitolo 9-1 / 73

Strutture dati. Il che cosa e il come. F. Damiani - Alg. & Lab. 04/05

Esempio: Tombola! Vogliamo progettare una applicazione che realizza il gioco della tombola Versione semplificata: un banco, un

Concorrenza e sincronizzazione

Classi astratte e progettazione OOP Esempio: l enciclopedia degli animali

Fondamenti di Informatica e Laboratorio T-AB T-15 Strutture dati

9 - Array. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Calcolare x n = x x x (n volte)

3) Descrivere l architettura di un elaboratore tramite astrazione a livelli

Riassunto: cos è la OOP? classi astratte, interfacce, classi interne. Scaletta. Figura con area()? Figura senza area()? Stefano Mizzaro 1.

STRINGHE IN JAVA In Java, le stringhe non sono pezzi di memo-ria con dentro dei caratteri, come in C: sono oggetti appartenenti alla classe

Corso di Laurea in Ingegneria Gestionale Esame di Informatica a.a luglio 2011

Sul pattern Iterator

Thread in Java. Thread = flusso di esecuzione indipendente nel codice del programma

Programmazione = decomposizione basata su astrazioni

Variabili e Metodi di classe Interfacce e Package Gestione di File in Java

Esonero del corso di Programmazione a Oggetti

Laboratorio Progettazione Web Le funzioni in PHP. Angelica Lo Duca IIT-CNR 2012/2013

Multithreading in Java I parte. Lorenzo Gallucci

Liste doppie. Doubly Linked Lists. GT: 6.2 (e 3.3) Argomenti della lezione

Astrazioni sui dati : Specifica di Tipi di Dato Astratti in Java

Corso di Algoritmi e Strutture Dati con Laboratorio. Tipi di dato pila e coda

Programmazione II Compitino (Vers. B)

Esempio 2: Subtyping

Ricerca e ordinamento su array di oggetti. Corso di Programmazione 2 Esercitazione 5

Fondamenti di informatica T-1 (A K) Esercitazione 2: Linguaggio Java, basi e controllo del flusso

14 - Metodi e Costruttori

TIPI PRIMITIVI E CLASSI WRAPPER

Programmazione Orientata agli Oggetti in Linguaggio Java

A. Lorenzi, A. Rizzi Java. Programmazione ad oggetti e applicazioni Android Istituto Italiano Edizioni Atlas

Introduzione alla Programmazione in Java attraverso un esempio commentato

Esonero del corso di Programmazione a Oggetti

I Thread. un thread è uno stream di esecuzione del programma

Corso sul linguaggio Java

Elementi lessicali. Lezione 4. La parole chiave. Elementi lessicali. Elementi lessicali e espressioni logiche. Linguaggi di Programmazione I

Concetti base programmazione. Antonio Gallo

Multithreading. Multithreading/2

Fondamenti di Informatica. Algoritmi di Ricerca e di Ordinamento

Futures Esempi di codice

Introduzione Programmazione Java

Indice. Prefazione. 3 Oggetti e Java 53

Metodi di una Collection

Fondamenti di Informatica 1. Prof. B.Buttarazzi A.A. 2010/2011

Oggetti e classi. Cos è un oggetto

Programmazione Java Avanzata Programmazione Object- Oriented in Java

Fondamenti di Informatica T1 Mappe

Collezioni. (a cura del Prof. Marco Patella)

Uso di classi e oggetti. Prof. Francesco Acarino IIS Altiero Spinelli Via Leopardi 132 Sesto San Giovanni

Introduzione a Java. Riferimenti

Funzioni, Stack e Visibilità delle Variabili in C

Esercitazione n 2. Obiettivi

ELEMENTI DI INFORMATICA L-B. Ing. Claudia Chiusoli

ESERCIZI JAVA. Esercizi sulle Interfacce. Esercizio 1:

Modelli di programmazione parallela

Programmazione con Java

Programmazione a Oggetti e JAVA. Prof. B.Buttarazzi A.A. 2012/2013

Transcript:

Java I nuovi paradigmi e linguaggi tendono a semplificare il lavoro del programmatore, nascondendo dentro le librerie (o i costrutti del linguaggio) parte della programmazione necessaria Da Java 5, in un ciclo, si può scorrere una lista o un array senza dover dare il valore di inizio e fine dell indice List<String> nomi;... for (String nome : nomi) {... Da Java 7, si può evitare di indicare il tipo durante l istanziazione di sottotipi di Collection, lasciando al compilatore l inferenza List<String> nomi = new LinkedList<>(); Java è un linguaggio imperativo, tuttavia Java 8 include caratteristiche tipiche della programmazione funzionale. La programmazione funzionale è in genere più concisa, espressiva, e facile da parallelizzare rispetto alla programmazione ad oggetti Classi Anonime In Java Da Java 1.1 si possono usare classi anonime per implementare interfacce public interface Hello { public interface Hello { public void greetings(string s); public void greetings(string s); public class Sera { public class Sera { private Hello myh; private Hello myh; public Sera(Hello h) { public Sera(Hello h) { myh = h; myh = h; public void saluti() { public void saluti() { myh.greetings("buonasera"); myh.greetings("buonasera"); public class Saluti implements Hello { public class MainSaluti { @Override public static void main(string[] args) { public void greetings(string s) { Sera ser = new Sera(new Hello() { System.out.println("Ciao, "+s); @Override public void greetings(string s) { System.out.println("Ciao, "+s); public class MainSaluti { public static void main(string[] args) { ); Sera ser = new Sera(new Saluti()); 1 2 Implementazione Interfaccia La classe anonima implementa il metodo dell interfaccia, e tale codice viene dato al momento dell istanziazione Sera ser = new Sera(new Hello() { @Override public void greetings(string s) { System.out.println("Ciao, "+s); ); Java 8 permette di evitare di passare i preamboli (o codice standard, boilerplate), e di implementare solo il comportamento nuovo, se l interfaccia ha un solo metodo // Java 8 Sera ser = new Sera(s -> System.out.println("Ciao, " + s)); Si implementa solo il codice del corpo del metodo Espressioni Lambda s -> System.out.println("Ciao, " + s) Il codice sopra è un espressione lambda Un espressione lambda è una funzione anonima, che prende in ingresso zero o più parametri, a sinistra del segno freccia, fra parentesi tonde, e un blocco di codice, a destra del segno freccia Un espressione lambda che prende in ingresso due parametri è (x, y) -> x + y I parametri in ingresso sono x e y, a sinistra della freccia, il cui tipo è determinato automaticamente, nella maggior parte dei casi Il codice a destra della freccia x + y implementa la somma dei due parametri in ingresso, il valore risultante viene restituito 3 4

Design Pattern Observer // ConcreteSubject public class Note extends Observable { private String n = "Una nota"; public void aggiungi() { setchanged(); notifyobservers(n); Si crea un istanza del ConcreteSubject Note Note n = new Note(); Si passa il comportamento del ConcreteObserver nel momento in cui si chiama n.addobserver() sul ConcreteSubject n n.addobserver( (s, o) -> System.out.println("Osservatore di "+s.getclass()+" per "+o)); Chiamando il metodo n.aggiungi() si ha l output Osservatore di class Note per Una nota public class Trova { private List<String> nomi = Arrays.asList("Nobita", "Nobi", "Suneo", "Honekawa", "Shizuka", "Minamoto", "Takeshi", "Gouda"); // in stile imperativo public void trovaimper() { boolean trovato = false; for (String nome : nomi) if (nome.equals("nobi")) { trovato = true; break; if (trovato) System.out.println("Nobi trovato"); else System.out.println("Nobi non trovato"); // in stile dichiarativo public void trovadichiar() { if (nomi.contains("nobi")) System.out.println("Nobi trovato"); else System.out.println("Nobi non trovato"); 5 6 Considerazioni L implementazione imperativa si serve di una variabile boolean come flag per indicare se l elemento è stato trovato. Inoltre si usa un ciclo per scorrere la lista e controllare se uscire dal ciclo Lo stile imperativo dà al programmatore il controllo di quel che il programma deve fare, tuttavia Bisogna implementare varie linee di codice, e molto spesso si hanno cicli che scorrono liste per trovare valori, calcolare somme, etc. Per capire cosa si vuol fare, dobbiamo prima leggere tanti dettagli all interno del corpo del ciclo Il ciclo è esterno al codice che implementa la lista (l iterazione è esterna) Stile Funzionale Lo stile di programmazione funzionale è dichiarativa. La programmazione funzionale aggiunge allo stile dichiarativo funzioni di ordine più alto In Java si possono passare oggetti ai metodi, creare oggetti dentro i metodi, e ritornare oggetti dai metodi In Java 8 si possono passare funzioni ai metodi, creare funzioni dentro i metodi e ritornare funzioni dai metodi Un metodo è una parte di una classe, mentre una funzione non è associata ad una classe Un metodo o una funzione che ricevono, creano o ritornano una funzione, si considerano essere funzioni di ordine più alto Nella versione dichiarativa alcuni dettagli dell implementazione sono nella libreria sottostante, l iterazione è interna 7 8

Java Collection Le librerie di Java hanno tante interfacce e classi collection. Collection è un interfaccia che definisce i metodi add(), remove(), size(), contains(), containsall(), etc. List definisce i metodi get(), indexof(), set(), etc. get add contains remove ArrayList costante costante O(n) O(n) LinkedList O(n) costante O(n) costante TreeSet O(lg n) O(lg n) <<interface>> List <<abstract>> AbstractList <<interface>> Collection <<interface>> Set <<abstract>> AbstractSet Java 8 Java 8 introduce i metodi di default per le interfacce Ciò ha permesso di avere metodi nuovi per le interfacce esistenti, senza compromettere la compatibilità delle applicazioni conformi a precedenti versioni di Java stream() è un metodo di default dell interfaccia Collection I metodi di default non agiscono sullo stato, invece le classi astratte che hanno metodi implementati possono avere costruttori e metodi che agiscono sullo stato LinkedList ArrayList Vector TreeSet ArrayList è un array espandibile, ovvero cresce del 50% quando non vi è più spazio. Gli elementi sono contigui, quindi l accesso è veloce LinkedList è una lista, ogni elemento contiene un riferimento al successivo e al precedente Vector è simile ad ArrayList, ma è synchronized 9 10 Stile Funzionale // in stile funzionale private void trovafunc() { if (nomi.stream().filter(s -> s.equals("nobi")).count() > 0) System.out.println("Nobi trovato"); else System.out.println("Nobi non trovato"); stream() è un metodo di default dell interfaccia Collection Permette di costruire operazioni complesse con un approccio funzionale Restituisce un oggetto Stream che non è una nuova collezione, ma dà un modo per creare una collezione Sull oggetto Stream si possono chiamare varie operazioni (per es. filter()), ed alcune di esse accettano funzioni come argomenti 11 Filter nomi.stream().filter(s -> s.equals("nobi")).count() A filter() di Stream si passa la funzione s -> s.equals("nobi") L espressione lambda (o funzione) s -> s.equals("nobi") Ha il parametro in ingresso s che è un elemento della Collection nomi Restituisce un boolean Il valore di ritorno di filter() è uno stream che contiene solo gli elementi dello stream iniziale che soddisfano la condizione fornita filter() è lazy, ovvero operazione intermedia, non crea un valore in uscita, se non necessario count() è eager, ovvero operazione terminale, genera un valore e forza l esecuzione delle precedenti operazioni Tutte le operazioni che restituiscono uno Stream sono lazy 12

public class Pagamenti { private List<Float> importi = new ArrayList<>(); // in stile imperativo public float calcolasommaimper() { float risultato = 0; for (float v : importi) risultato += v; return risultato; Reduce importi.stream().reduce(0f, (v, accum) -> accum + v); reduce() di Stream applica la funzione che gli viene passata (secondo argomento), in questo caso la somma, a tutti gli elementi dello stream e accumula un risultato // in stile funzionale public float calcolasomma() { return importi.stream().reduce(0f, (v, accum) -> accum + v); ArrayList è un implementazione di List basata su array di dimensione variabile, i metodi get() e add() eseguono in un tempo costante, quando l array ha ancora spazio (altrimenti prima della add bisogna espandere l array) reduce() è eager accum = 0f; for (v : stream) accum += v; return accum; L espressione lambda (v, accum) -> accum + v Implementa la somma di ciascun valore v dello stream con la variabile accum, che inizialmente vale 0f (vedi primo parametro di reduce()) e successivamente vale la somma precedentemente calcolata 13 14 public class Person { private String nome; private int eta; public Person(String n, int e) { nome = n; eta = e; public String getnome() { return nome; public int geteta() { return eta; new Person("Taro", 21), new Person("Ian", 19), new Person("Al", 16)); Calcoliamo la somma delle età in stile funzionale int somma = p.stream().map(person::geteta).reduce(0, (v, t) -> v + t); 15 int somma = 0; for (Person x : p) somma += x.geteta(); Map int somma = p.stream().map(person::geteta).reduce(0, (x, t) -> x + t); map() di Stream restituisce uno stream contenente i risultati dell esecuzione della funzione passata come argomento di map(), in questo caso geteta(), su tutti gli elementi dello stream iniziale map() è lazy Ovvero, a ciascun elemento dello stream iniziale map() fa corrispondere un risultato. In questo caso, ogni elemento dello stream iniziale è un istanza di Person, map() restituisce uno stream contenente il valore del campo eta di ciascuna istanza di Person La funzione che si passa a map() è il metodo geteta() di Person, la sintassi è Person::getEta 16

Collect new Person("Taro", 21), new Person("Ian", 19), new Person("Al", 16)); Ricaviamo la lista delle età List<Integer> e = p.stream().map(x -> x.geteta()).collect(collectors.tolist()); Come prima, map() restituisce uno stream con i valori delle età, e l espressione lambda passata dice come trasformare ciascun elemento dello stream L operazione collect() di Stream permette di raggruppare i risultati e prende in ingresso un Collector. La classe Collectors implementa metodi utili per raggruppamenti, il metodo tolist() restituisce un Collector che accumula elementi in una List Programmazione Parallela I processori attuali hanno vari core, due per i portatili, quattro per i desktop, dodici per i server La programmazione parallela è più difficile di quella sequenziale e usare bene l hardware risulta più complicato In Java, la classe Thread permette di lanciare un nuovo thread di esecuzione, ma spesso bisogna risolvere i problemi di corsa critica, usando opportunamente synchronized, wait, notify Java 5 mette a disposizione Lock, Esecutori, etc. Le operazioni map(), filter(), etc. di Stream eseguono sequenzialmente, su un unico core, o in parallelo? Le operazioni map() e filter() di Stream sono stateless, ovvero non tengono uno stato durante l esecuzione, quindi il risultato non dipende dall ordine in cui i singoli elementi su cui eseguono vengono prelevati List<Integer> e = new LinkedList<>(); for (Person x : p) Questo facilita grandemente la parallelizzazione e.add(x.geteta()); 17 18 Stream Paralleli Collection ha i metodi di default stream() e parallelstream() Il metodo parallelstream() possibilmente dà uno stream parallelo. Quindi per avere l esecuzione parallela basta usare il metodo parallelstream() (niente più bisogno di thread e sincronizzazione, per molti casi) Le prestazioni dipendono da: (i) numero di elementi dello stream, (ii) operazioni da svolgere, (iii) hardware, e (iv) tipo di Collection su cui si invoca l operazione Dichiarativo O Funzionale? Data la lista con le istanze di Person new Person("Taro", 21), new Person("Ian", 19), new Person("Al", 16)); Lo stile dichiarativo non funzionerebbe if (p.contains("saro")) System.out.println("Saro trovato"); Poiché la lista p contiene istanze di Person e non valori String La Collection potrebbe essere ArrayList, LinkedList, etc., con tempi di accesso diversi (vedere tabella precedente) Lo stile funzionale consente di estrarre il campo nome, inoltre permette di valutare una funzione ad-hoc, quindi è molto più flessibile e potente Eseguendo su milioni di elementi il seguente codice, le prestazioni migliorano (su hardware con più core) per ArrayList, Vector, TreeSet; p.stream() non migliorano quando si usa LinkedList a causa dell accesso sequenziale.filter(s -> s.getnome().equals("saro")) c = nomi.parallelstream().count().map(s -> s.touppercase()).filter(s -> s.equals( NOBI )).count(); 19 20

Esercizio: Ricerca Su Lista Data la lista di istanze di Person, trovare il nome della persona che è più grande (di età) fra quelli che hanno meno di 20 anni new Person("Taro", 21), new Person("Ian", 19), new Person("Al", 16)); In versione imperativa, se volessimo scorrere la lista solo una volta private void trovapersonaimper() { Person pmax = null; for (Person x : p) if (x.geteta() < 20) { if (pmax == null) pmax = x; if (pmax.geteta() < x.geteta()) pmax = x; if (pmax!= null) System.out.println("persona: " + pmax.getnome()); Ricerca Su Lista La versione funzionale è private void trovapersona() { Optional<Person> pmax = p.stream().filter(x -> x.geteta() < 20).max(Comparator.comparing(x -> x.geteta())); if (pmax.ispresent()) System.out.println("persona: " + pmax.get().getnome()); filter() separa gli elementi che soddisfano la condizione sull età, prende in ingresso la funzione da eseguire sugli elementi dello stream max() trova il valore massimo, è eager, prende un Comparator, restituisce un Optional, max() opera in modo simile a reduce() L operazione comparing() di Comparator prende una funzione che estrae una chiave e restituisce un Comparator Optional è un tipo di Java 8, rappresenta un valore che può esistere o meno, se esiste il metodo ispresent() darà un valore true, per estrarre il valore si usa get() Il corpo del ciclo ha varie condizioni, queste rendono il codice più difficile da comprendere 21 22 Conta Parole Data una stringa contare le occorrenze di ciascuna parola String ha il metodo split() che prende un espressione regolare e restituisce un array di stringhe in cui ciascun elemento è una parte della stringa iniziale HashMap è una tabella per coppie chiave - valore, può contenere solo una volta una certa chiave. Il metodo get() permette di prelevare il valore, data la chiave. Il metodo put() inserisce la coppia chiave - valore String frase = "ci sono tre mele sul tavolo e tre mele nella cesta"; List<String> l = Arrays.asList(frase.split("[\\s+,;]+")); La versione funzionale Conta Parole Map<String, Long> mp = l.stream().collect(collectors.groupingby(s -> s, Collectors.counting())); Collectors ha metodi utili che permettono di raggruppare elementi (abbiamo visto precedentemente il metodo tolist()) Il metodo groupingby() prende in ingresso una funzione per la classificazione, come primo argomento, e un Collector come secondo argomento Map<String, Long> mp = new HashMap<>(); for (String p : l) { if (mp.containskey(p)) mp.put(p, mp.get(p)+1); else mp.put(p, 1l); Il metodo counting() restituisce un Collector, che è una operazione di tipo reduce, ovvero conteggio di elementi con la stessa chiave Il metodo collect() che prende il suddetto Collector genera una HashMap con coppie chiave, ovvero parola, e valore, ovvero conteggio occorrenza 23 24