Java Lambda-expressies (met voorbeelden)

In dit artikel zullen we leren over Java lambda-expressie en het gebruik van lambda-expressie met functionele interfaces, generieke functionele interface en stream-API met behulp van voorbeelden.

De lambda-uitdrukking werd voor het eerst geïntroduceerd in Java 8. Haar belangrijkste doel is om de expressieve kracht van de taal te vergroten.

Maar voordat we met lambda's beginnen, moeten we eerst functionele interfaces begrijpen.

Wat is functionele interface?

Als een Java-interface één en slechts één abstracte methode bevat, wordt deze functionele interface genoemd. Deze enige methode specificeert het beoogde doel van de interface.

Bijvoorbeeld de Runnableinterface van pakket java.lang; is een functionele interface omdat het slechts één methode vormt, namelijk run().

Voorbeeld 1: definieer een functionele interface in java

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

In het bovenstaande voorbeeld heeft de interface MyInterface slechts één abstracte methode getValue (). Daarom is het een functionele interface.

Hier hebben we de annotatie gebruikt @FunctionalInterface. De annotatie dwingt de Java-compiler om aan te geven dat de interface een functionele interface is. Daarom staat het niet toe om meer dan één abstracte methode te hebben. Het is echter niet verplicht.

In Java 7 werden functionele interfaces beschouwd als Single Abstract Methods of SAM- type. SAM's werden vaak geïmplementeerd met anonieme klassen in Java 7.

Voorbeeld 2: SAM implementeren met anonieme klassen 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(); ) )

Uitgang :

 Ik heb zojuist de Runnable Functional Interface geïmplementeerd.

Hier kunnen we een anonieme klasse doorgeven aan een methode. Dit helpt bij het schrijven van programma's met minder codes in Java 7. De syntaxis was echter nog steeds moeilijk en er waren veel extra regels code nodig.

Java 8 breidde de kracht van SAM's uit door een stap verder te gaan. Aangezien we weten dat een functionele interface slechts één methode heeft, hoeft het niet nodig te zijn om de naam van die methode te definiëren wanneer u deze als argument doorgeeft. Lambda-expressie stelt ons in staat om precies dat te doen.

Inleiding tot lambda-uitdrukkingen

Lambda-expressie is in wezen een anonieme of naamloze methode. De lambda-uitdrukking wordt niet zelfstandig uitgevoerd. In plaats daarvan wordt het gebruikt om een ​​methode te implementeren die is gedefinieerd door een functionele interface.

Hoe lambda-expressie in Java te definiëren?

Hier is hoe we lambda-expressie in Java kunnen definiëren.

 (parameter list) -> lambda body

De nieuwe operator ( ->) die wordt gebruikt, staat bekend als een pijloperator of een lambda-operator. De syntaxis is op dit moment misschien niet duidelijk. Laten we enkele voorbeelden bekijken,

Stel dat we een methode als deze hebben:

 double getPiValue() ( return 3.1415; )

We kunnen deze methode schrijven met lambda-expressie als:

 () -> 3.1415

Hier heeft de methode geen parameters. Daarom bevat de linkerkant van de operator een lege parameter. De rechterkant is de lambda-body die de actie van de lambda-expressie specificeert. In dit geval retourneert het de waarde 3,1415.

Soorten Lambda Body

Op Java bestaat het lambda-lichaam uit twee typen.

1. Een lichaam met een enkele uitdrukking

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

Dit type lambda-lichaam staat bekend als het expressielichaam.

2. Een body die bestaat uit een blok code.

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

Dit type lambda-body staat bekend als een block-body. Met de blockbody kan de lambda-body meerdere statements bevatten. Deze uitspraken staan ​​tussen de accolades en u moet een puntkomma achter de accolades plaatsen.

Opmerking : voor het blokhoofdgedeelte kunt u een retourinstructie hebben als het lichaam een ​​waarde retourneert. De hoofdtekst van de expressie vereist echter geen return-instructie.

Voorbeeld 3: Lambda-expressie

Laten we een Java-programma schrijven dat de waarde van Pi retourneert met behulp van de lambda-uitdrukking.

Zoals eerder vermeld, wordt een lambda-expressie niet op zichzelf uitgevoerd. Het vormt eerder de implementatie van de abstracte methode die wordt gedefinieerd door de functionele interface.

We moeten dus eerst een functionele interface definiëren.

 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()); ) )

Uitgang :

 Waarde van Pi = 3,1415

In het bovenstaande voorbeeld

  • We hebben een functionele interface gemaakt met de naam MyInterface. Het bevat een enkele abstracte methode met de naamgetPiValue()
  • Binnen de klasse Main hebben we een verwijzing naar MyInterface verklaard. Merk op dat we een referentie van een interface kunnen declareren, maar we kunnen geen interface instantiëren. Dat is,
     // it will throw an error MyInterface ref = new myInterface(); // it is valid MyInterface ref;
  • We hebben vervolgens een lambda-uitdrukking aan de referentie toegewezen.
     ref = () -> 3.1415;
  • Ten slotte noemen we de methode getPiValue()met behulp van de referentie-interface. Wanneer
     System.out.println("Value of Pi = " + ref.getPiValue());

Lambda-expressies met parameters

Tot nu toe hebben we lambda-expressies gemaakt zonder enige parameters. Net als bij methoden kunnen lambda-expressies echter ook parameters hebben. Bijvoorbeeld,

 (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.

We kunnen ook onze eigen uitdrukkingen definiëren op basis van de syntaxis die we hierboven hebben geleerd. Dit stelt ons in staat om de regels code drastisch te verminderen, zoals we in het bovenstaande voorbeeld hebben gezien.

Interessante artikelen...