Object orienteed
Programming
Espressioni Lambda
A cura di Roberto Musa
Gruppo Musa ICT - Creazione Siti Internet e Marketing
Cosa sono le Espressioni Lamba
Le espressioni Lambda sono di fatto delle funzioni anonime dove si indica
direttamente, senza assegnare un nome, parametri restituiti e codice della
funzione.
La struttura base di una espressione lambda è il seguente:
([tipoA a, tipoB b,… ])->{Codice…}
Tutto ciò che può essere dedotto dal contesto è abbreviabile come parametri
restituiti, tipi e parentisi.
Nel caso si scriva una sola riga di codice, petanto con le grafe omesse, per
restituire un valore va omesso il «return».
Esempio di espressione lambda ridotta al minimo:
e -> e.getEl(); //nessuna parentisi tonda perché restituisce un solo
paramentro e nessun tipo in quanto deducibile dal contesto, inoltre sono omesse
grafe e return in quanto il codice è costituito da una sola istruzione
Perché le Espressioni Lamba
Java nasce come paradigma ad oggetti e mai in passato ha voluto discostarsi da
questa sua caratteristica che lo rendeva ottimo in certe applicazioni ma lo
indebolisce con l’esplosione del multicore computing a cui la programmazione
funzionale si adatta meglio.
Nell’ottica di permettere la programmazione funzionale e di sintetizzare al
massimo il codice, Java 8 reinserisce le Espressioni Lambda.
Quando usare le Espressioni Lambda
Le Espressioni Lambda si usano per ridefinire il Metodo Astratto (SAM: Single Abstract
Metod) di un’interfaccia funzionale in base al contesto.
Ad esempio un filtro può dipendere dal contesto o dalla richiesta ed ecco che con le
espressioni lambda possiamo ridefinirlo di volta in volta in base alle nostre necessità.
Esempio Videoteca: (Nell’esempio vediamo un metodo chiamare il SAM dell’IF che
definiremo tramite Espressione Lambda nel al momento di utilizzarla nel main)
…
Videoteca videoteca = new Videoteca();
//Filtro per Valutazione:
Film[] beiFilm = videoteca. getFilmFiltrati (film->
film.getMediaRecensioni() > 3);
//Filtro per genere:
Film[] fantasy = videoteca. getFilmFiltrati (film->
‘’Fantasy’’.equals(film.getGenere()));
@FunctionalInterface
public Interface FiltroFilm {
boolean filtra (Film film);
}
public Class Videoteca {
public Film[] getFilmFiltrati (FiltroFilm
filtroFilm) {
…
if (filtroFilm.filtra(film))
filmFiltrati[i++]=film;
…
}
}
Esercizio
 Creare un sistema Videoteca contenente un elenco di Film di cui son noti
Codice, Titolo, Autore, Genere, Durata e Media Recensioni.
 Il sistema deve poter restituire:
 L’elenco dei Film per autore;
 L’elenco dei film per genere;
 L’elenco dei film con media voto superiore alla soglia indicata;
 L’elenco dei film per durata.
Assumere di essere in possesso di un database di film in un file csv in cui ogni
film è in una riga ed i campi sono separati da virgola.
Soluzione: La classe Films
package Videoteca;
public class Films {
private int codice;
private String titolo;
private String autore;
private String genere;
private int durata;
private double mediaRecensioni;
public Films(int codice, String
titolo, String autore, String genere, int
durata, double mediaRecensioni){
this.codice = codice;
this.titolo = titolo;
this.autore = autore;
this.genere = genere;
this.durata = durata;
this.mediaRecensioni =
mediaRecensioni;
}
public void setCodice(int codice){
this.codice = codice;
}
public void setTitolo(String titolo){
this.titolo = titolo;
}
public void setAutore(String autore){
this.autore = autore;
}
public void setGenere(String
genere){
this.genere = genere;
}
public void setDurata(int durata){
this.durata = durata;
}
public void
setMediaRecensioni(double
mediaRecensioni){
this.mediaRecensioni =
mediaRecensioni;
}
public int getCodice(){
return this.codice;
}
public String getTitolo(){
return this.titolo;
}
public String getAutore(){
return this.autore;
}
public String getGenere(){
return this.genere;
}
public int getDurata(){
return this.durata;
}
public double getMediaRecensioni(){
return this.mediaRecensioni;
}
}
Soluzione: L’Interfaccia Funzionale
FiltroFilm
package Videoteca;
@FunctionalInterface
public interface FiltroFilm {
boolean filtra(Films film);
}
Soluzione: La classe Videoteca
package Videoteca;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class Videoteca {
private HashMap<Integer, Films> films;
public Videoteca(Films[] listaFilm){
this.films = new HashMap<Integer, Films>();
for (Films film : listaFilm) {
this.films.put(film.getCodice(), film);
}
}
public Videoteca(List<Films> listaFilm){
this.films = new HashMap<Integer, Films>();
for (Films film : listaFilm) {
this.films.put(film.getCodice(), film);
}
}
@SuppressWarnings("unchecked")
public Videoteca(File listaFilm){
//letturaFile e creazione mappa di Films
//List<String> readAllLines(Path path)
ArrayList<Films> filmList = new ArrayList<Films>();
try {
String SEPARATOR = ",";
BufferedReader listaReader = new
BufferedReader(new FileReader(listaFilm));
filmList = (ArrayList<Films>)
listaReader.lines().map(line -> Arrays.asList(line.split(SEPARATOR)));
listaReader.close();
for (Films film : filmList) {
this.films.put(film.getCodice(), film);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Soluzione: La classe Videoteca
public List<Films> cerca(FiltroFilm filtroFilm){
ArrayList<Films> filmList = new ArrayList<Films>(this.films.values());
ArrayList<Films> filmFiltrati = new ArrayList<Films>();
for (Films film : filmList) {
if (filtroFilm.filtra(film))
filmFiltrati.add(film);
}
return filmFiltrati;
}
}
Soluzione: Il main
package Videoteca;
import java.io.File;
import java.util.List;
import java.util.Scanner;
public class Mediateca {
public static void main(String[] args) {
File listafilm = new File(args[0]);
// TODO Auto-generated method stub
Videoteca videoteca = new Videoteca(listafilm);
//Film per autore;
String autore;
Scanner a = new Scanner(System.in);
autore = a.nextLine();
a.close();
List<Films> filmAutore = videoteca.cerca(film-
>autore.equals(film.getAutore()));
//Film per genere;
String genere;
Scanner g = new Scanner(System.in);
genere = g.nextLine();
g.close();
List<Films> filmGenere = videoteca.cerca(film-
>genere.equals(film.getGenere()));
//Film per media;
int soglia;
Scanner s = new Scanner(System.in);
soglia = Integer.valueOf(s.nextLine());
s.close();
List<Films> beiFilm = videoteca.cerca(film-
>film.getMediaRecensioni() > soglia);
//Film per durata minima;
int durata;
Scanner d = new Scanner(System.in);
durata = Integer.valueOf(d.nextLine());
d.close();
List<Films> filmLunghi = videoteca.cerca(film-
>film.getDurata() > durata);
}
}
Soluzione: Osservazioni
Nella soluzione offerta possiamo osservare come nel metodo «cerca()» della classe
Videoteca venga richiamato il metodo astratto dell’Interfaccia Funzionale FiltroFilm.
Come in ogni Interfaccia il Metodo non è implementato quindi ci è dato sapere cosa ci
verrà restituito (in questo caso un boolean) ma non come questo verrà elaborato.
Le espressioni Lambda che abbiamo usato nel nostro esempio vanno a ridefinire il
metodo di volta in volta, permettendoci di avere risultati differenti senza dover
richiamare o creare nuovi metodi.
Per effetto dell’ereditarietà molte volte l’Interfaccia Funzionale non è esplicitata,
caso evidente con l’uso delle collezioni e degli stream che implementano Interfacce
quali Iterable e Comparable.
Es:
List<String> strings = new ArrayList<>();
strings.stream().forEach((string) -> {
System.out.println("Content: " +
string);
});
Es2:
strings.parallelStream().
filter(s -> s.contains("java")).
forEach((string) -> {
System.out.println("Content: " +
string);
});
}

OOP Scano di Montiferro - Java 8: Espressioni Lambda

  • 1.
    Object orienteed Programming Espressioni Lambda Acura di Roberto Musa Gruppo Musa ICT - Creazione Siti Internet e Marketing
  • 2.
    Cosa sono leEspressioni Lamba Le espressioni Lambda sono di fatto delle funzioni anonime dove si indica direttamente, senza assegnare un nome, parametri restituiti e codice della funzione. La struttura base di una espressione lambda è il seguente: ([tipoA a, tipoB b,… ])->{Codice…} Tutto ciò che può essere dedotto dal contesto è abbreviabile come parametri restituiti, tipi e parentisi. Nel caso si scriva una sola riga di codice, petanto con le grafe omesse, per restituire un valore va omesso il «return». Esempio di espressione lambda ridotta al minimo: e -> e.getEl(); //nessuna parentisi tonda perché restituisce un solo paramentro e nessun tipo in quanto deducibile dal contesto, inoltre sono omesse grafe e return in quanto il codice è costituito da una sola istruzione
  • 3.
    Perché le EspressioniLamba Java nasce come paradigma ad oggetti e mai in passato ha voluto discostarsi da questa sua caratteristica che lo rendeva ottimo in certe applicazioni ma lo indebolisce con l’esplosione del multicore computing a cui la programmazione funzionale si adatta meglio. Nell’ottica di permettere la programmazione funzionale e di sintetizzare al massimo il codice, Java 8 reinserisce le Espressioni Lambda.
  • 4.
    Quando usare leEspressioni Lambda Le Espressioni Lambda si usano per ridefinire il Metodo Astratto (SAM: Single Abstract Metod) di un’interfaccia funzionale in base al contesto. Ad esempio un filtro può dipendere dal contesto o dalla richiesta ed ecco che con le espressioni lambda possiamo ridefinirlo di volta in volta in base alle nostre necessità. Esempio Videoteca: (Nell’esempio vediamo un metodo chiamare il SAM dell’IF che definiremo tramite Espressione Lambda nel al momento di utilizzarla nel main) … Videoteca videoteca = new Videoteca(); //Filtro per Valutazione: Film[] beiFilm = videoteca. getFilmFiltrati (film-> film.getMediaRecensioni() > 3); //Filtro per genere: Film[] fantasy = videoteca. getFilmFiltrati (film-> ‘’Fantasy’’.equals(film.getGenere())); @FunctionalInterface public Interface FiltroFilm { boolean filtra (Film film); } public Class Videoteca { public Film[] getFilmFiltrati (FiltroFilm filtroFilm) { … if (filtroFilm.filtra(film)) filmFiltrati[i++]=film; … } }
  • 5.
    Esercizio  Creare unsistema Videoteca contenente un elenco di Film di cui son noti Codice, Titolo, Autore, Genere, Durata e Media Recensioni.  Il sistema deve poter restituire:  L’elenco dei Film per autore;  L’elenco dei film per genere;  L’elenco dei film con media voto superiore alla soglia indicata;  L’elenco dei film per durata. Assumere di essere in possesso di un database di film in un file csv in cui ogni film è in una riga ed i campi sono separati da virgola.
  • 6.
    Soluzione: La classeFilms package Videoteca; public class Films { private int codice; private String titolo; private String autore; private String genere; private int durata; private double mediaRecensioni; public Films(int codice, String titolo, String autore, String genere, int durata, double mediaRecensioni){ this.codice = codice; this.titolo = titolo; this.autore = autore; this.genere = genere; this.durata = durata; this.mediaRecensioni = mediaRecensioni; } public void setCodice(int codice){ this.codice = codice; } public void setTitolo(String titolo){ this.titolo = titolo; } public void setAutore(String autore){ this.autore = autore; } public void setGenere(String genere){ this.genere = genere; } public void setDurata(int durata){ this.durata = durata; } public void setMediaRecensioni(double mediaRecensioni){ this.mediaRecensioni = mediaRecensioni; } public int getCodice(){ return this.codice; } public String getTitolo(){ return this.titolo; } public String getAutore(){ return this.autore; } public String getGenere(){ return this.genere; } public int getDurata(){ return this.durata; } public double getMediaRecensioni(){ return this.mediaRecensioni; } }
  • 7.
    Soluzione: L’Interfaccia Funzionale FiltroFilm packageVideoteca; @FunctionalInterface public interface FiltroFilm { boolean filtra(Films film); }
  • 8.
    Soluzione: La classeVideoteca package Videoteca; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; public class Videoteca { private HashMap<Integer, Films> films; public Videoteca(Films[] listaFilm){ this.films = new HashMap<Integer, Films>(); for (Films film : listaFilm) { this.films.put(film.getCodice(), film); } } public Videoteca(List<Films> listaFilm){ this.films = new HashMap<Integer, Films>(); for (Films film : listaFilm) { this.films.put(film.getCodice(), film); } } @SuppressWarnings("unchecked") public Videoteca(File listaFilm){ //letturaFile e creazione mappa di Films //List<String> readAllLines(Path path) ArrayList<Films> filmList = new ArrayList<Films>(); try { String SEPARATOR = ","; BufferedReader listaReader = new BufferedReader(new FileReader(listaFilm)); filmList = (ArrayList<Films>) listaReader.lines().map(line -> Arrays.asList(line.split(SEPARATOR))); listaReader.close(); for (Films film : filmList) { this.films.put(film.getCodice(), film); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
  • 9.
    Soluzione: La classeVideoteca public List<Films> cerca(FiltroFilm filtroFilm){ ArrayList<Films> filmList = new ArrayList<Films>(this.films.values()); ArrayList<Films> filmFiltrati = new ArrayList<Films>(); for (Films film : filmList) { if (filtroFilm.filtra(film)) filmFiltrati.add(film); } return filmFiltrati; } }
  • 10.
    Soluzione: Il main packageVideoteca; import java.io.File; import java.util.List; import java.util.Scanner; public class Mediateca { public static void main(String[] args) { File listafilm = new File(args[0]); // TODO Auto-generated method stub Videoteca videoteca = new Videoteca(listafilm); //Film per autore; String autore; Scanner a = new Scanner(System.in); autore = a.nextLine(); a.close(); List<Films> filmAutore = videoteca.cerca(film- >autore.equals(film.getAutore())); //Film per genere; String genere; Scanner g = new Scanner(System.in); genere = g.nextLine(); g.close(); List<Films> filmGenere = videoteca.cerca(film- >genere.equals(film.getGenere())); //Film per media; int soglia; Scanner s = new Scanner(System.in); soglia = Integer.valueOf(s.nextLine()); s.close(); List<Films> beiFilm = videoteca.cerca(film- >film.getMediaRecensioni() > soglia); //Film per durata minima; int durata; Scanner d = new Scanner(System.in); durata = Integer.valueOf(d.nextLine()); d.close(); List<Films> filmLunghi = videoteca.cerca(film- >film.getDurata() > durata); } }
  • 11.
    Soluzione: Osservazioni Nella soluzioneofferta possiamo osservare come nel metodo «cerca()» della classe Videoteca venga richiamato il metodo astratto dell’Interfaccia Funzionale FiltroFilm. Come in ogni Interfaccia il Metodo non è implementato quindi ci è dato sapere cosa ci verrà restituito (in questo caso un boolean) ma non come questo verrà elaborato. Le espressioni Lambda che abbiamo usato nel nostro esempio vanno a ridefinire il metodo di volta in volta, permettendoci di avere risultati differenti senza dover richiamare o creare nuovi metodi. Per effetto dell’ereditarietà molte volte l’Interfaccia Funzionale non è esplicitata, caso evidente con l’uso delle collezioni e degli stream che implementano Interfacce quali Iterable e Comparable. Es: List<String> strings = new ArrayList<>(); strings.stream().forEach((string) -> { System.out.println("Content: " + string); }); Es2: strings.parallelStream(). filter(s -> s.contains("java")). forEach((string) -> { System.out.println("Content: " + string); }); }