Java Lambda Expressions (Με παραδείγματα)

Σε αυτό το άρθρο, θα μάθουμε για την έκφραση Java λάμδα και τη χρήση της έκφρασης λάμδα με λειτουργικές διεπαφές, γενική λειτουργική διεπαφή και ροή API με τη βοήθεια παραδειγμάτων.

Η έκφραση λάμδα παρουσιάστηκε για πρώτη φορά στην Java 8. Κύριος στόχος της είναι η αύξηση της εκφραστικής δύναμης της γλώσσας.

Όμως, πριν πάμε σε λάμδα, πρέπει πρώτα να κατανοήσουμε λειτουργικές διεπαφές.

Τι είναι η λειτουργική διεπαφή;

Εάν μια διεπαφή Java περιέχει μία και μόνο μια αφηρημένη μέθοδο, τότε ονομάζεται λειτουργική διεπαφή Αυτή η μόνη μέθοδος καθορίζει τον επιδιωκόμενο σκοπό της διεπαφής.

Για παράδειγμα, η Runnableδιεπαφή από το πακέτο java.lang. είναι μια λειτουργική διεπαφή επειδή αποτελεί μόνο μία μέθοδο, δηλαδή run().

Παράδειγμα 1: Ορίστε μια λειτουργική διεπαφή σε java

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

Στο παραπάνω παράδειγμα, η διεπαφή MyInterface έχει μόνο μία αφηρημένη μέθοδο getValue (). Ως εκ τούτου, είναι μια λειτουργική διεπαφή.

Εδώ, χρησιμοποιήσαμε τον σχολιασμό @FunctionalInterface. Ο σχολιασμός αναγκάζει τον μεταγλωττιστή Java να υποδείξει ότι η διεπαφή είναι μια λειτουργική διεπαφή. Ως εκ τούτου, δεν επιτρέπει να έχουμε περισσότερες από μία αφηρημένες μεθόδους. Ωστόσο, δεν είναι υποχρεωτικό.

Στην Java 7, οι λειτουργικές διεπαφές θεωρήθηκαν ως μέθοδοι μιας αφηρημένης μεθόδου ή τύπου SAM . Τα SAM εφαρμόζονταν συνήθως με Ανώνυμες τάξεις στο Java 7.

Παράδειγμα 2: Εφαρμόστε το SAM με ανώνυμες τάξεις στο 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(); ) )

Έξοδος :

 Μόλις εφάρμοσα τη λειτουργική διεπαφή Runnable.

Εδώ, μπορούμε να περάσουμε μια ανώνυμη τάξη σε μια μέθοδο. Αυτό βοηθά στη σύνταξη προγραμμάτων με λιγότερους κωδικούς στην Java 7. Ωστόσο, η σύνταξη ήταν ακόμα δύσκολη και απαιτήθηκαν πολλές επιπλέον γραμμές κώδικα.

Η Java 8 επέκτεινε τη δύναμη των SAM προχωρώντας ένα βήμα πιο πέρα. Δεδομένου ότι γνωρίζουμε ότι μια λειτουργική διεπαφή έχει μόνο μία μέθοδο, δεν θα πρέπει να ορίζεται το όνομα αυτής της μεθόδου όταν την μεταδίδουμε ως επιχείρημα. Η έκφραση Lambda μας επιτρέπει να κάνουμε ακριβώς αυτό.

Εισαγωγή στις εκφράσεις λάμδα

Η έκφραση της λάμδα είναι ουσιαστικά μια ανώνυμη ή ανώνυμη μέθοδος. Η έκφραση λάμδα δεν εκτελείται από μόνη της. Αντ 'αυτού, χρησιμοποιείται για την εφαρμογή μιας μεθόδου που ορίζεται από μια λειτουργική διεπαφή.

Πώς να ορίσετε την έκφραση lambda στην Java;

Εδώ είναι πώς μπορούμε να ορίσουμε την έκφραση lambda στην Java.

 (parameter list) -> lambda body

Ο νέος χειριστής ( ->) που χρησιμοποιείται είναι γνωστός ως τελεστής βέλους ή χειριστής λάμδα. Η σύνταξη μπορεί να μην είναι σαφής αυτή τη στιγμή. Ας εξερευνήσουμε μερικά παραδείγματα,

Ας υποθέσουμε ότι έχουμε μια μέθοδο όπως αυτή:

 double getPiValue() ( return 3.1415; )

Μπορούμε να γράψουμε αυτή τη μέθοδο χρησιμοποιώντας έκφραση λάμδα ως:

 () -> 3.1415

Εδώ, η μέθοδος δεν έχει παραμέτρους. Ως εκ τούτου, η αριστερή πλευρά του χειριστή περιλαμβάνει μια κενή παράμετρο. Η δεξιά πλευρά είναι το σώμα λάμδα που καθορίζει τη δράση της έκφρασης λάμδα. Σε αυτήν την περίπτωση, επιστρέφει την τιμή 3.1415.

Τύποι σώματος λάμδα

Στην Java, το σώμα λάμδα είναι δύο τύπων.

1. Ένα σώμα με μία μόνο έκφραση

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

Αυτός ο τύπος σώματος λάμδα είναι γνωστός ως σώμα έκφρασης.

2. Ένα σώμα που αποτελείται από ένα μπλοκ κώδικα.

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

Αυτός ο τύπος σώματος λάμδα είναι γνωστός ως σώμα σώματος. Το σώμα μπλοκ επιτρέπει στο σώμα λάμδα να περιλαμβάνει πολλές δηλώσεις. Αυτές οι δηλώσεις περικλείονται μέσα στα άγκιστρα και πρέπει να προσθέσετε ένα τελείωμα μετά τα άγκιστρα.

Σημείωση : Για το σώμα μπλοκ, μπορείτε να έχετε μια δήλωση επιστροφής εάν το σώμα επιστρέφει μια τιμή. Ωστόσο, το σώμα έκφρασης δεν απαιτεί δήλωση επιστροφής.

Παράδειγμα 3: Έκφραση Lambda

Ας γράψουμε ένα πρόγραμμα Java που επιστρέφει την τιμή του Pi χρησιμοποιώντας την έκφραση lambda.

Όπως αναφέρθηκε προηγουμένως, μια έκφραση λάμδα δεν εκτελείται από μόνη της. Αντίθετα, αποτελεί την εφαρμογή της αφηρημένης μεθόδου που ορίζεται από τη λειτουργική διεπαφή.

Επομένως, πρέπει πρώτα να ορίσουμε μια λειτουργική διεπαφή.

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

Έξοδος :

 Τιμή Pi = 3.1415

Στο παραπάνω παράδειγμα,

  • Έχουμε δημιουργήσει μια λειτουργική διεπαφή που ονομάζεται MyInterface. Περιέχει μια μεμονωμένη αφηρημένη μέθοδο που ονομάζεταιgetPiValue()
  • Μέσα στην κύρια τάξη, δηλώσαμε μια αναφορά στο MyInterface. Σημειώστε ότι μπορούμε να δηλώσουμε μια αναφορά μιας διεπαφής αλλά δεν μπορούμε να δημιουργήσουμε μια διεπαφή. Αυτό είναι,
     // it will throw an error MyInterface ref = new myInterface(); // it is valid MyInterface ref;
  • Στη συνέχεια, εκχωρήσαμε μια έκφραση λάμδα στην αναφορά.
     ref = () -> 3.1415;
  • Τέλος, καλούμε τη μέθοδο getPiValue()χρησιμοποιώντας τη διεπαφή αναφοράς. Πότε
     System.out.println("Value of Pi = " + ref.getPiValue());

Lambda Expressions με παραμέτρους

Μέχρι τώρα έχουμε δημιουργήσει εκφράσεις λάμδα χωρίς καμία παράμετρο. Ωστόσο, παρόμοια με τις μεθόδους, οι εκφράσεις λάμδα μπορούν επίσης να έχουν παραμέτρους. Για παράδειγμα,

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

Μπορούμε επίσης να ορίσουμε τις δικές μας εκφράσεις με βάση τη σύνταξη που μάθαμε παραπάνω. Αυτό μας επιτρέπει να μειώσουμε δραστικά τις γραμμές κώδικα όπως είδαμε στο παραπάνω παράδειγμα.

ενδιαφέροντα άρθρα...