Java Lambda avaldised (koos näidetega)

Selles artiklis õpime näidete abil Java lambda ekspressiooni ja lambda ekspressiooni kasutamist koos funktsionaalsete liideste, üldise funktsionaalse liidese ja voo API-ga.

Lambda väljend võeti esmakordselt kasutusele Java 8-s. Selle peamine eesmärk on suurendada keele väljendusvõimet.

Kuid enne lambdasse jõudmist peame kõigepealt mõistma funktsionaalseid liideseid.

Mis on funktsionaalne liides?

Kui Java-liides sisaldab ühte ja ainult ühte abstraktset meetodit, nimetatakse seda funktsionaalseks liideseks. See ainult üks meetod täpsustab liidese sihtotstarvet.

Näiteks Runnableliides paketist java.lang; on funktsionaalne liides, kuna see moodustab ainult ühe meetodi, st run().

Näide 1: määratlege Java-s funktsionaalne liides

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

Ülaltoodud näites on liidesel MyInterface ainult üks abstraktne meetod getValue (). Seega on see funktsionaalne liides.

Siin oleme kasutanud märkust @FunctionalInterface. Annotatsioon sunnib Java kompilaatorit näitama, et liides on funktsionaalne liides. Seega ei luba omada rohkem kui ühte abstraktset meetodit. See pole siiski kohustuslik.

Java 7-s käsitleti funktsionaalseid liideseid ühe abstraktse meetodina või SAM- tüüpi. SAM-e rakendati tavaliselt Java 7 anonüümsete klassidega.

Näide 2: Rakendage Java-s anonüümsete klassidega SAM

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

Väljund :

 Rakendasin just Runnable Functional Interface'i.

Siinkohal võime anonüümse klassi edasi anda meetodile. See aitab kirjutada Java 7-s vähem koodidega programme. Süntaks oli siiski keeruline ja vaja oli palju koodiridu.

Java 8 laiendas SAM-ide võimsust, astudes sammu edasi. Kuna me teame, et funktsionaalsel liidesel on ainult üks meetod, ei peaks selle argumendina edastamisel olema vaja selle meetodi nime määratleda. Lambda väljend võimaldab meil täpselt seda teha.

Sissejuhatus lambda väljenditesse

Lambda väljend on sisuliselt anonüümne või nimetu meetod. Lambda-väljend ei käivitu iseenesest. Selle asemel kasutatakse seda funktsionaalse liidese määratletud meetodi rakendamiseks.

Kuidas määratleda lambda väljend Java-s?

Nii saame määratleda lambda väljenduse Java-s.

 (parameter list) -> lambda body

Kasutatav uus operaator ( ->) on tuntud kui nooleoperaator või lambdaoperaator. Süntaks ei pruugi praegu selge olla. Uurime mõningaid näiteid,

Oletame, et meil on selline meetod:

 double getPiValue() ( return 3.1415; )

Selle meetodi võime kirjutada lambda-avaldise abil järgmiselt:

 () -> 3.1415

Siin pole meetodil parameetreid. Seega sisaldab operaatori vasak pool tühja parameetrit. Parem külg on lambda keha, mis määrab lambda avaldise tegevuse. Sel juhul tagastab see väärtuse 3,1415.

Lambda kere tüübid

Jaavas on lambda keha kahte tüüpi.

1. Ühe avaldisega keha

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

Seda tüüpi lambda keha tuntakse keha väljendusena.

2. Keha, mis koosneb koodiplokist.

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

Seda tüüpi lambda keha tuntakse plokk-korpusena. Ploki korpus võimaldab lambda kehal lisada mitu lauset. Need avaldused on sulghäälikute sees ja pärast traksid tuleb lisada poolkool.

Märkus . Ploki keha puhul võib teil olla tagastamislause, kui keha tagastab väärtuse. Väljend keha ei vaja siiski tagasilause.

Näide 3: Lambda väljend

Kirjutame Java-programmi, mis tagastab pi väärtuse lambda-avaldise abil.

Nagu varem mainitud, ei täideta lambda väljendit iseseisvalt. Pigem moodustab see funktsionaalse liidese määratletud abstraktse meetodi rakendamise.

Niisiis, kõigepealt peame määratlema funktsionaalse liidese.

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

Väljund :

 Pi väärtus = 3,1415

Ülaltoodud näites

  • Oleme loonud funktsionaalse liidese nimega MyInterface. See sisaldab ühte abstraktset meetodit nimegagetPiValue()
  • Main-klassi sees oleme kuulutanud viite MyInterface'ile. Pange tähele, et me võime deklareerida liidese viite, kuid me ei saa liidest liidestada. See on,
     // it will throw an error MyInterface ref = new myInterface(); // it is valid MyInterface ref;
  • Seejärel määrasime viitele lambda-avaldise.
     ref = () -> 3.1415;
  • Lõpuks nimetame meetodit getPiValue()referentsliidese abil. Millal
     System.out.println("Value of Pi = " + ref.getPiValue());

Parameetritega lambda-väljendid

Siiani oleme loonud lambda väljendid ilma parameetriteta. Kuid sarnaselt meetoditele võivad lambda-väljendid omada ka parameetreid. Näiteks,

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

Samuti võime ülalpool õpitud süntaksile tuginedes määratleda omaenda väljendid. See võimaldab meil koodiridu drastiliselt vähendada, nagu nägime ülaltoodud näites.

Huvitavad Artiklid...