„Java Lambda“ išraiškos (su pavyzdžiais)

Šiame straipsnyje su pavyzdžių pagalba sužinosime apie „Java lambda“ išraišką ir „lambda“ išraiškos naudojimą su funkcinėmis sąsajomis, bendrą funkcinę sąsają ir srauto API.

Pirmą kartą „lambda“ išraiška buvo įvesta „Java 8“. Pagrindinis jos tikslas - padidinti išraiškinę kalbos galią.

Tačiau prieš pradėdami naudotis lambda, pirmiausia turime suprasti funkcines sąsajas.

Kas yra funkcinė sąsaja?

Jei „Java“ sąsajoje yra vienas ir tik vienas abstraktus metodas, tai vadinama funkcine sąsaja. Šis tik vienas metodas nurodo numatomą sąsajos tikslą.

Pavyzdžiui, Runnablesąsaja iš paketo java.lang; yra funkcinė sąsaja, nes ji sudaro tik vieną metodą, t run().

1 pavyzdys: Apibrėžkite „Java“ funkcinę sąsają

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

Ankstesniame pavyzdyje sąsajoje „MyInterface“ yra tik vienas abstraktus metodas getValue (). Vadinasi, tai yra funkcinė sąsaja.

Čia mes panaudojome anotaciją @FunctionalInterface. Anotacija priverčia „Java“ kompiliatorių nurodyti, kad sąsaja yra funkcinė sąsaja. Vadinasi, neleidžia turėti daugiau nei vieno abstraktaus metodo. Tačiau tai nėra privaloma.

„Java 7“ funkcinės sąsajos buvo laikomos „Single Abstract Methods“ arba „ SAM“ tipais. SAM buvo paprastai diegiami naudojant „Java 7“ anonimines klases.

2 pavyzdys: įgyvendinkite SAM su anoniminėmis klasėmis „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(); ) )

Išvestis :

 Aš ką tik įdiegiau „Runnable Functional Interface“.

Čia mes galime perduoti anoniminę klasę metodui. Tai padeda rašyti programas su mažiau kodų „Java 7“. Tačiau sintaksė vis dar buvo sunki ir reikėjo daug papildomų kodo eilučių.

„Java 8“ išplėtė SAM galią žengdama žingsnį toliau. Kadangi žinome, kad funkcinė sąsaja turi tik vieną metodą, nereikėtų apibrėžti to metodo pavadinimo, kai jis perduodamas kaip argumentas. Lambda išraiška leidžia mums tai padaryti.

Lambda posakių įvadas

Lambda išraiška iš esmės yra anoniminis arba neįvardytas metodas. Lambda išraiška nevykdoma atskirai. Vietoj to jis naudojamas metodui, apibrėžtam funkcinės sąsajos, įgyvendinti.

Kaip apibrėžti „lambda“ išraišką „Java“?

Štai kaip mes galime apibrėžti „lambda“ išraišką „Java“.

 (parameter list) -> lambda body

Naudojamas naujas operatorius ( ->) yra žinomas kaip rodyklių operatorius arba lambda operatorius. Sintaksė šiuo metu gali būti neaiški. Panagrinėkime keletą pavyzdžių,

Tarkime, mes turime tokį metodą:

 double getPiValue() ( return 3.1415; )

Mes galime parašyti šį metodą naudodami lambda išraišką kaip:

 () -> 3.1415

Čia metodas neturi jokių parametrų. Vadinasi, kairėje operatoriaus pusėje yra tuščias parametras. Dešinė pusė yra lambda kūnas, nurodantis lambda išraiškos veikimą. Tokiu atveju ji grąžina vertę 3,1415.

Lambda korpuso tipai

Java kalba lambda korpusas yra dviejų tipų.

1. Kūnas su viena išraiška

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

Šis lambda kūno tipas yra žinomas kaip kūno išraiška.

2. Kūnas, kurį sudaro kodo blokas.

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

Šis lambda korpuso tipas yra žinomas kaip blokinis korpusas. Bloko korpusas leidžia lambda kūnui įtraukti kelis teiginius. Šie teiginiai yra uždaromi tarp petnešų ir po petnešomis turite pridėti kabliataškį.

Pastaba : Bloko kūnui galite turėti grąžinimo sakinį, jei kūnas grąžina vertę. Tačiau išraiškos kūnas nereikalauja grąžinimo sakinio.

3 pavyzdys: lambda išraiška

Parašykime „Java“ programą, kuri grąžina Pi reikšmę naudodama „lambda“ išraišką.

Kaip minėta anksčiau, lambda išraiška nevykdoma atskirai. Veikiau jis formuoja abstrakčiojo metodo, apibrėžto funkcine sąsaja, įgyvendinimą.

So, we need to define a functional interface first.

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

Output:

 Value of Pi = 3.1415

In the above example,

  • We have created a functional interface named MyInterface. It contains a single abstract method named getPiValue()
  • Inside the Main class, we have declared a reference to MyInterface. Note that we can declare a reference of an interface but we cannot instantiate an interface. That is,
     // it will throw an error MyInterface ref = new myInterface(); // it is valid MyInterface ref;
  • We then assigned a lambda expression to the reference.
     ref = () -> 3.1415;
  • Finally, we call the method getPiValue() using the reference interface. When
     System.out.println("Value of Pi = " + ref.getPiValue());

Lambda Expressions with parameters

Till now we have created lambda expressions without any parameters. However, similar to methods, lambda expressions can also have parameters. For example,

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

Mes taip pat galime apibrėžti savo išraiškas, remdamiesi aukščiau išmokta sintakse. Tai leidžia mums smarkiai sumažinti kodo eilutes, kaip matėme aukščiau pateiktame pavyzdyje.

Įdomios straipsniai...