//Novitá di JAVA8 : Lambda Expressions

Novitá di JAVA8 : Lambda Expressions

0 votes
Share on FacebookShare on Google+Tweet about this on TwitterEmail this to someonePrint this page

This post has already been read 340 times!

In questi ultimi mesi sono stato occupato e non ho avuto molto tempo per stare dietro al blog, fortunatamente @Davide, @Fabrizio e @Alessio hanno portato avanti il progetto anche senza il mio aiuto.

In questi giorni peró ho pensato di ricominciare a scrivere qualche articolo, sto pensando di iniziare una sezione in cui si trattano argomenti medio/avanzati di Java 8. Sono sicuro che tutti i lettori conoscono alla perfezione le ultime novitá di Java 8, pero a volte un piccolo ripasso non puo fare certo male, dato che alcuni concetti non sono poi cosí scontati.
Successivamente, se la sezione ha un certo interesse e vediamo qualche commento potremmo poi continuare con argomenti che genealmente rimangono piú indigesti e che possono aiutare a risolvere facilmente o con piu stile alcuni problemi quotidiani.
Gli argomenti che ho pensato trattare inizialmente in questa serie di articoli sono :

  • Lambda Expressions, cosa sono
  • java default method, perché
  • Come gli stream possono migliorare la mia vita.
  • Perche usare le interfacce funzionali
  • Novitá per le date in Java8

una volta terminati questi temi penso proporre qualcosa di meno recente peró sicuramente utile, per tutti quelli che programmano in java 8 peró sono rimasti ad uno stile di 15 anni fa, e usano i generici solo per evitarsi un cast, o usano l’unboxing per errore :p

Le Espressioni in Lambda

Le espressioni Lambda sono uno dei concetti che considero piu difficili da capire bene, da anni ormai che mi trovo a parlare con uno sviluppatore del progetto GNU e ogni volta che iniziamo a scrivere un po di codice inizia a usare le cosiddette funzioni senza nome. Il concetto di base realmente é semplice, una lambda expression non é altro che una funzione che non ha un nome per essere chiamata, quindi realmente non puó essere chiamata in modo esplicito come se fosse una funzione normale. Quindi perché io dovrei mai definirmi una funzione se non la posso chiamare direttamente ?
Esistono dei casi in cui una funzione senza nome ha un senso, soprattutto per rendere il codice meno pensante e piu dinamico.

iniziamo definendoci la nostra funzione fattoriale :

static int fact(int x) {
return x == 0 ? 1 : x * (fact(x - 1));
}

per chi non avesse dimestichezza con la notazione su una sola linea, la funzione non fa altro che :

static int fact2(int x) {
if (x == 0)
return 1;
else
return x * fact2(x - 1);
}

per poterla chiamare basterá all interno del main aggiungere :

System.out.println("fact():" + fact(5));

se un giorno avessimo bisogno peró di cambiare quello che fa la nostra funzione saremmo costretti a scriverci una nuova funzione dichiarandola con un nuovo nome.
quello che possiamo fare invece é ricorrere alla API Function :

java.util.function.Function<T, R>

dove T sta per il tipo di input e R per il tipo di ritorno.

Definiamoci quindi la nostra funzione che avrá un parametro in input intero en un output intero :

static Function<Integer, Integer> f;

nel nostro main successivamente é possibile inizializzare questa funzione in qualsiasi momento e chiamarla :

f = (x) -> {return x == 0 ? 1 : x * (f.apply(x - 1));};
System.out.println("fact():" + f.apply(5));

fin qui tutto normale, non abbiamo risparmiato molto, alla fine la definizione della funzione non é che occupi molto. Bene adesso iniziamo a divertirci un po di piu, decidiamo cambiare la definizione della nostra funzione al passo successivo :

f = (x) -> {return x == 0 ? 1 : x * (f.apply(x - 1));};
System.out.println("fact():" + f.apply(5));
f = (x) -> {return x == 0 || x == 1 ? 2 : x * (f.apply(x - 2));};
System.out.println("fact():" + f.apply(5));

effettivamente questo é perfettamente lecito, nel secondo passo la nostra funzione cambierá il proprio risultato. Questo che a prima vista potrebbe essere una cosa di poco peso, nel prossimo passo vedremo un esempio di come queste funzioni senza nome possono essere immagazzinate in una lista per poter essere chiamate successivamente.

List<Function<Integer, Integer>> lf = new ArrayList<Function<Integer, Integer>>();

f = (x) -> {return x == 0 ? 1 : x * (f.apply(x - 1));};

lf.add(f);
lf.add((x) -> {return x == 0 || x == 1 ? 2 : x * (f.apply(x - 2));});
lf.add(x -> { return x+1 ;});

for(Function<Integer, Integer> funct : lf )
System.out.println("Risultato : "+ funct.apply(5));

infatti dall outpit possiamo vedere come queste funzioni vengono chiamate una ad una :

Risultato : 120
Risultato : 30
Risultato : 6

questo apre un sacco di possibilitá,  prima delle funzioni senza nome avrebbero avuto bisogno di centinaia di linee di codice in Java,  adesso tutto questo puó essere fatto con poche linee di codice.

Nei prossimi articoli vedremo esempi di lambda expression con Interfacce, classi senza nome e Stream.
Ricordo di commentare l’articolo in modo da poter migliorare questa serie di tutorial per eventuali errori, omissioni, chiarmenti e consigli.

infine vi lascio il codice completo dell esempio :

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class factorial {

static int fact(int x) {
return x == 0 ? 1 : x * (fact(x - 1));
}

static int fact2(int x) {
if (x == 0)
return 1;
else
return x * fact2(x - 1);
}

static Function<Integer, Integer> f;

public static void main(String args[]) {

System.out.println("fact():" + fact(5));
System.out.println("fact():" + fact2(5));
f = (x) -> {return x == 0 ? 1 : x * (f.apply(x - 1));};
System.out.println("fact():" + f.apply(5));
f = (x) -> {return x == 0 || x == 1 ? 2 : x * (f.apply(x - 2));};
System.out.println("fact():" + f.apply(5));

List<Function<Integer, Integer>> lf = new ArrayList<Function<Integer, Integer>>();

f = (x) -> {return x == 0 ? 1 : x * (f.apply(x - 1));};

lf.add(f);
lf.add((x) -> {return x == 0 || x == 1 ? 2 : x * (f.apply(x - 2));});
lf.add(x -> { return x+1 ;});

for(Function<Integer, Integer> funct : lf )
System.out.println("Risultato : "+ funct.apply(5));
}

}

a presto

Matteo