Java Lambda izteiksmes (ar piemēriem)

Šajā rakstā mēs uzzināsim par Java lambda izteiksmi un lambda izteiksmes izmantošanu ar funkcionālajām saskarnēm, vispārīgo funkcionālo saskarni un straumes API ar piemēru palīdzību.

Lambda izteiksme pirmo reizi tika ieviesta Java 8. Tās galvenais mērķis ir palielināt valodas izteiksmes spēku.

Bet, pirms nokļūstam lambdās, mums vispirms ir jāsaprot funkcionālās saskarnes.

Kas ir funkcionālā saskarne?

Ja Java saskarnē ir viena un tikai viena abstrakta metode, to sauc par funkcionālo interfeisu. Šī tikai viena metode norāda saskarnes paredzēto mērķi.

Piemēram, Runnablesaskarne no pakotnes java.lang; ir funkcionāla saskarne, jo tā ir tikai viena metode, ti run().

1. piemērs: Definējiet funkcionālo saskarni Java

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

Iepriekš minētajā piemērā saskarnei MyInterface ir tikai viena abstrakta metode getValue (). Tādējādi tas ir funkcionāls interfeiss.

Šeit mēs izmantojām anotāciju @FunctionalInterface. Anotācija liek Java kompilatoram norādīt, ka interfeiss ir funkcionāls interfeiss. Tādējādi neļauj izmantot vairāk nekā vienu abstraktu metodi. Tomēr tas nav obligāti.

Java 7 funkcionālās saskarnes tika uzskatītas par Single Abstract Methods vai SAM tipu. SAM parasti tika ieviesti ar anonīmām klasēm Java 7.

2. piemērs: ieviesiet SAM ar anonīmām klasēm 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(); ) )

Izeja :

 Es tikko ieviesu Runnable Functional Interface.

Šeit mēs varam nodot anonīmu klasi metodei. Tas palīdz rakstīt programmas ar mazāk kodiem Java 7. Tomēr sintakse joprojām bija sarežģīta, un bija nepieciešamas daudzas papildu koda rindas.

Java 8 paplašināja SAM spēku, dodoties soli tālāk. Tā kā mēs zinām, ka funkcionālajam interfeisam ir tikai viena metode, nododot to kā argumentu, nav jādefinē šīs metodes nosaukums. Lambda izteiksme ļauj mums to izdarīt tieši tā.

Ievads lambda izteicienos

Lambda izteiksme būtībā ir anonīma vai nenosaukta metode. Lambda izteiksme netiek izpildīta atsevišķi. Tā vietā to izmanto, lai ieviestu funkcionālās saskarnes definētu metodi.

Kā definēt lambda izteiksmi Java valodā?

Lūk, kā mēs varam definēt lambda izteiksmi Java.

 (parameter list) -> lambda body

Izmantotais jaunais operators ( ->) ir pazīstams kā bultiņu operators vai lambda operators. Sintakse šobrīd var nebūt skaidra. Izpētīsim dažus piemērus,

Pieņemsim, ka mums ir šāda metode:

 double getPiValue() ( return 3.1415; )

Mēs varam uzrakstīt šo metodi, izmantojot lambda izteiksmi kā:

 () -> 3.1415

Šeit metodei nav parametru. Tādējādi operatora kreisajā pusē ir tukšs parametrs. Labā puse ir lambda ķermenis, kas norāda lambda izteiksmes darbību. Šajā gadījumā tas atgriež vērtību 3.1415.

Lambda korpusa veidi

Java valodā lambda korpuss ir divu veidu.

1. Ķermenis ar vienu izteiksmi

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

Šāda veida lambda ķermenis ir pazīstams kā izteiksmes ķermenis.

2. Pamatteksts, kas sastāv no koda bloka.

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

Šis lambda ķermeņa tips ir pazīstams kā bloku korpuss. Bloka korpuss ļauj lambda ķermenim iekļaut vairākus paziņojumus. Šie paziņojumi ir ievietoti lencēs, un pēc lencēm jums jāpievieno semikols.

Piezīme . Bloka pamattekstam var būt atgriešanās priekšraksts, ja pamatteksts atgriež vērtību. Tomēr izteiksmes ķermenim nav nepieciešams atgriešanās paziņojums.

3. piemērs: Lambda izteiksme

Uzrakstīsim Java programmu, kas atgriež Pi vērtību, izmantojot izteiksmi lambda.

Kā minēts iepriekš, lambda izteiksme netiek izpildīta atsevišķi. Drīzāk tas veido funkcionālās saskarnes definētās abstraktās metodes ieviešanu.

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.

Mēs varam arī definēt paši savus izteicienus, pamatojoties uz sintaksi, ko mēs iemācījāmies iepriekš. Tas ļauj mums krasi samazināt koda rindiņas, kā redzējām iepriekš minētajā piemērā.

Interesanti raksti...