Espressioni Java Lambda (con esempi)

In questo articolo, apprenderemo l'espressione lambda Java e l'uso dell'espressione lambda con interfacce funzionali, interfaccia funzionale generica e API di flusso con l'aiuto di esempi.

L'espressione lambda è stata introdotta per la prima volta in Java 8. Il suo obiettivo principale è aumentare la potenza espressiva del linguaggio.

Ma, prima di entrare in lambda, dobbiamo prima capire le interfacce funzionali.

Cos'è l'interfaccia funzionale?

Se un'interfaccia Java contiene uno e un solo metodo astratto, viene definita interfaccia funzionale. Questo solo un metodo specifica lo scopo previsto dell'interfaccia.

Ad esempio, l' Runnableinterfaccia dal pacchetto java.lang; è un'interfaccia funzionale perché costituisce un solo metodo, ad es run().

Esempio 1: definire un'interfaccia funzionale in java

 import java.lang.FunctionalInterface; @FunctionalInterface public interface MyInterface( // the single abstract method double getValue(); )

Nell'esempio sopra, l'interfaccia MyInterface ha un solo metodo astratto getValue (). Quindi, è un'interfaccia funzionale.

Qui abbiamo usato l'annotazione @FunctionalInterface. L'annotazione forza il compilatore Java a indicare che l'interfaccia è un'interfaccia funzionale. Quindi, non consente di avere più di un metodo astratto. Tuttavia, non è obbligatorio.

In Java 7, le interfacce funzionali erano considerate come metodi astratti singoli o tipo SAM . I SAM venivano comunemente implementati con classi anonime in Java 7.

Esempio 2: implementare SAM con classi anonime in java

 public class FunctionInterfaceTest ( public static void main(String() args) ( // anonymous class new Thread(new Runnable() ( @Override public void run() ( System.out.println("I just implemented the Runnable Functional Interface."); ) )).start(); ) )

Uscita :

 Ho appena implementato l'interfaccia funzionale eseguibile.

Qui possiamo passare una classe anonima a un metodo. Questo aiuta a scrivere programmi con meno codici in Java 7. Tuttavia, la sintassi era ancora difficile ed erano necessarie molte righe di codice extra.

Java 8 ha esteso la potenza di un SAM facendo un ulteriore passo avanti. Poiché sappiamo che un'interfaccia funzionale ha un solo metodo, non dovrebbe essere necessario definire il nome di quel metodo quando lo si passa come argomento. L'espressione lambda ci consente di fare esattamente questo.

Introduzione alle espressioni lambda

L'espressione lambda è, essenzialmente, un metodo anonimo o senza nome. L'espressione lambda non viene eseguita da sola. Invece, viene utilizzato per implementare un metodo definito da un'interfaccia funzionale.

Come definire l'espressione lambda in Java?

Ecco come possiamo definire l'espressione lambda in Java.

 (parameter list) -> lambda body

L'operatore new ( ->) utilizzato è noto come operatore freccia o operatore lambda. La sintassi potrebbe non essere chiara al momento. Esploriamo alcuni esempi,

Supponiamo di avere un metodo come questo:

 double getPiValue() ( return 3.1415; )

Possiamo scrivere questo metodo usando l'espressione lambda come:

 () -> 3.1415

Qui, il metodo non ha parametri. Quindi, il lato sinistro dell'operatore include un parametro vuoto. Il lato destro è il corpo lambda che specifica l'azione dell'espressione lambda. In questo caso, restituisce il valore 3.1415.

Tipi di corpo lambda

In Java, il corpo lambda è di due tipi.

1. Un corpo con una sola espressione

 () -> System.out.println("Lambdas are great");

Questo tipo di corpo lambda è noto come corpo dell'espressione.

2. Un corpo che consiste in un blocco di codice.

 () -> ( double pi = 3.1415; return pi; );

Questo tipo di corpo lambda è noto come corpo a blocchi. Il corpo del blocco consente al corpo lambda di includere più istruzioni. Queste istruzioni sono racchiuse tra parentesi graffe e devi aggiungere un punto e virgola dopo le parentesi graffe.

Nota : per il corpo del blocco, è possibile avere un'istruzione return se il corpo restituisce un valore. Tuttavia, il corpo dell'espressione non richiede un'istruzione return.

Esempio 3: espressione Lambda

Scriviamo un programma Java che restituisca il valore di Pi utilizzando l'espressione lambda.

Come accennato in precedenza, un'espressione lambda non viene eseguita da sola. Piuttosto, costituisce l'implementazione del metodo astratto definito dall'interfaccia funzionale.

Quindi, dobbiamo prima definire un'interfaccia funzionale.

 import java.lang.FunctionalInterface; // this is functional interface @FunctionalInterface interface MyInterface( // abstract method double getPiValue(); ) public class Main ( public static void main( String() args ) ( // declare a reference to MyInterface MyInterface ref; // lambda expression ref = () -> 3.1415; System.out.println("Value of Pi = " + ref.getPiValue()); ) )

Uscita :

 Valore di Pi = 3,1415

Nell'esempio sopra,

  • Abbiamo creato un'interfaccia funzionale denominata MyInterface. Contiene un unico metodo astratto denominatogetPiValue()
  • All'interno della classe Main, abbiamo dichiarato un riferimento a MyInterface. Notare che possiamo dichiarare un riferimento di un'interfaccia ma non possiamo istanziare un'interfaccia. Questo è,
     // it will throw an error MyInterface ref = new myInterface(); // it is valid MyInterface ref;
  • Abbiamo quindi assegnato un'espressione lambda al riferimento.
     ref = () -> 3.1415;
  • Infine, chiamiamo il metodo getPiValue()utilizzando l'interfaccia di riferimento. quando
     System.out.println("Value of Pi = " + ref.getPiValue());

Espressioni lambda con parametri

Fino ad ora abbiamo creato espressioni lambda senza parametri. Tuttavia, analogamente ai metodi, anche le espressioni lambda possono avere parametri. Per esempio,

 (n) -> (n%2)==0

Here, the variable n inside the parenthesis is a parameter passed to the lambda expression. The lambda body takes the parameter and checks if it is even or odd.

Example 4: Using lambda expression with parameters

 @FunctionalInterface interface MyInterface ( // abstract method String reverse(String n); ) public class Main ( public static void main( String() args ) ( // declare a reference to MyInterface // assign a lambda expression to the reference MyInterface ref = (str) -> ( String result = ""; for (int i = str.length()-1; i>= 0 ; i--) result += str.charAt(i); return result; ); // call the method of the interface System.out.println("Lambda reversed = " + ref.reverse("Lambda")); ) )

Output:

 Lambda reversed = adbmaL

Generic Functional Interface

Till now we have used the functional interface that accepts only one type of value. For example,

 @FunctionalInterface interface MyInterface ( String reverseString(String n); )

The above functional interface only accepts String and returns String. However, we can make the functional interface generic, so that any data type is accepted. If you are not sure about generics, visit Java Generics.

Example 5: Generic Functional Interface and Lambda Expressions

 // GenericInterface.java @FunctionalInterface interface GenericInterface ( // generic method T func(T t); ) // GenericLambda.java public class Main ( public static void main( String() args ) ( // declare a reference to GenericInterface // the GenericInterface operates on String data // assign a lambda expression to it GenericInterface reverse = (str) -> ( String result = ""; for (int i = str.length()-1; i>= 0 ; i--) result += str.charAt(i); return result; ); System.out.println("Lambda reversed = " + reverse.func("Lambda")); // declare another reference to GenericInterface // the GenericInterface operates on Integer data // assign a lambda expression to it GenericInterface factorial = (n) -> ( int result = 1; for (int i = 1; i <= n; i++) result = i * result; return result; ); System.out.println("factorial of 5 = " + factorial.func(5)); ) )

Output:

 Lambda reversed = adbmaL factorial of 5 = 120

In the above example, we have created a generic functional interface named GenericInterface. It contains a generic method named func().

Here, inside the Main class,

  • GenericInterface reverse - creates a reference to the interface. The interface now operates on String type of data.
  • GenericInterface factorial - creates a reference to the interface. The interface, in this case, operates on the Integer type of data.

Lambda Expression and Stream API

The new java.util.stream package has been added to JDK8 which allows java developers to perform operations like search, filter, map, reduce, or manipulate collections like Lists.

For example, we have a stream of data (in our case a List of String) where each string is a combination of country name and place of the country. Now, we can process this stream of data and retrieve only the places from Nepal.

For this, we can perform bulk operations in the stream by the combination of Stream API and Lambda expression.

Example 6: Demonstration of using lambdas with the Stream API

 import java.util.ArrayList; import java.util.List; public class StreamMain ( // create an object of list using ArrayList static List places = new ArrayList(); // preparing our data public static List getPlaces()( // add places and country to the list places.add("Nepal, Kathmandu"); places.add("Nepal, Pokhara"); places.add("India, Delhi"); places.add("USA, New York"); places.add("Africa, Nigeria"); return places; ) public static void main( String() args ) ( List myPlaces = getPlaces(); System.out.println("Places from Nepal:"); // Filter places from Nepal myPlaces.stream() .filter((p) -> p.startsWith("Nepal")) .map((p) -> p.toUpperCase()) .sorted() .forEach((p) -> System.out.println(p)); ) )

Output:

 Places from Nepal: NEPAL, KATHMANDU NEPAL, POKHARA

In the above example, notice the statement,

 myPlaces.stream() .filter((p) -> p.startsWith("Nepal")) .map((p) -> p.toUpperCase()) .sorted() .forEach((p) -> System.out.println(p));

Here, we are using the methods like filter(), map() and forEach() of the Stream API. These methods can take a lambda expression as input.

Possiamo anche definire le nostre espressioni in base alla sintassi che abbiamo appreso sopra. Questo ci permette di ridurre drasticamente le righe di codice come abbiamo visto nell'esempio sopra.

Articoli interessanti...