Java Lambda izrazi (z primeri)

V tem članku bomo s pomočjo primerov spoznali lambda izraz Java in uporabo lambda izraza s funkcionalnimi vmesniki, splošnim funkcionalnim vmesnikom in API-jem toka.

Izraz lambda je bil prvič predstavljen v Javi 8. Njegov glavni cilj je povečati izrazno moč jezika.

Preden pa se lotimo lambdas, moramo najprej razumeti funkcionalne vmesnike.

Kaj je funkcijski vmesnik?

Če vmesnik Java vsebuje eno in samo eno abstraktno metodo, se imenuje funkcionalni vmesnik. Ta le ena metoda določa predvideni namen vmesnika.

Na primer Runnablevmesnik iz paketa java.lang; je funkcionalen vmesnik, ker predstavlja samo eno metodo, tj run().

Primer 1: Določite funkcijski vmesnik v javi

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

V zgornjem primeru ima vmesnik MyInterface samo eno abstraktno metodo getValue (). Zato je funkcionalen vmesnik.

Tu smo uporabili pripis @FunctionalInterface. Pripis prisili prevajalnik Java, da nakaže, da je vmesnik funkcionalen vmesnik. Zato ne dovoljuje imeti več kot ene abstraktne metode. Vendar pa ni obvezno.

V Javi 7 so bili funkcionalni vmesniki obravnavani kot enotne abstraktne metode ali vrste SAM . SAM-i so bili običajno implementirani z anonimnimi razredi v Javi 7.

Primer 2: Implementirajte SAM z anonimnimi razredi v javi

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

Izhod :

 Pravkar sem implementiral funkcionalen vmesnik Runnable.

Tu lahko anonimni razred prenesemo na metodo. To pomaga pri pisanju programov z manj kodami v Javi 7. Vendar je bila sintaksa še vedno težavna in zahtevalo je veliko dodatnih vrstic kode.

Java 8 je razširil moč SAM-ov s korakom naprej. Ker vemo, da ima funkcionalni vmesnik samo eno metodo, ne bi smelo biti treba določiti imena te metode, ko jo posredujemo kot argument. Lambda izraz nam omogoča točno to.

Uvod v lambda izraze

Lambda izraz je v bistvu anonimna ali neimenovana metoda. Izraz lambda se ne izvrši sam. Namesto tega se uporablja za izvajanje metode, ki jo definira funkcionalni vmesnik.

Kako definirati lambda izraz v Javi?

Tukaj je opisano, kako lahko v Java definiramo lambda izraz.

 (parameter list) -> lambda body

Uporabljeni novi operator ( ->) je znan kot operater puščice ali lambda operator. Sintaksa trenutno morda ni jasna. Poglejmo nekaj primerov,

Recimo, da imamo metodo, kot je ta:

 double getPiValue() ( return 3.1415; )

To metodo lahko zapišemo z uporabo lambda izraza kot:

 () -> 3.1415

Tu metoda nima nobenih parametrov. Zato leva stran operaterja vsebuje prazen parameter. Desna stran je lambda telo, ki določa delovanje lambda izraza. V tem primeru vrne vrednost 3.1415.

Vrste Lambda telesa

V Javi je lambda telo dveh vrst.

1. Telo z enim izrazom

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

Ta vrsta lambda telesa je znana kot izraz telo.

2. Telo, ki je sestavljeno iz bloka kode.

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

Ta vrsta lambda telesa je znana kot telo bloka. Telo bloka omogoča lambda telesu, da vključuje več stavkov. Ti stavki so zaprti v oklepajih in za oklepaji morate dodati podpičje.

Opomba : Za telo bloka lahko imate stavek return, če telo vrne vrednost. Vendar telo izraza ne zahteva stavka return.

Primer 3: Lambda izraz

Napišimo program Java, ki vrne vrednost Pi z uporabo lambda izraza.

Kot smo že omenili, se lambda izraz ne izvrši sam. Namesto tega tvori izvedbo abstraktne metode, ki jo definira funkcionalni vmesnik.

Torej, najprej moramo definirati funkcionalni vmesnik.

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

Izhod :

 Vrednost Pi = 3,1415

V zgornjem primeru je

  • Ustvarili smo funkcijski vmesnik z imenom MyInterface. Vsebuje eno samo abstraktno metodo z imenomgetPiValue()
  • V razredu Main smo razglasili sklic na MyInterface. Upoštevajte, da lahko navedemo sklic na vmesnik, vendar vmesnika ne moremo ustvariti. To je,
     // it will throw an error MyInterface ref = new myInterface(); // it is valid MyInterface ref;
  • Nato smo referenci dodelili lambda izraz.
     ref = () -> 3.1415;
  • Na koncu metodo pokličemo getPiValue()z referenčnim vmesnikom. Kdaj
     System.out.println("Value of Pi = " + ref.getPiValue());

Lambda izrazi s parametri

Do zdaj smo ustvarili lambda izraze brez kakršnih koli parametrov. Podobno kot metode imajo lahko tudi lambda izrazi parametre. Na primer

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

Svoje izraze lahko definiramo tudi na podlagi sintakse, ki smo se je naučili zgoraj. To nam omogoča drastično zmanjšanje vrstic kode, kot smo videli v zgornjem primeru.

Zanimive Članki...