Ekspresi Lambda Java (Dengan Contoh)

Pada artikel ini, kita akan belajar tentang ekspresi lambda Java dan penggunaan ekspresi lambda dengan antarmuka fungsional, antarmuka fungsional generik, dan API aliran dengan bantuan contoh.

Ekspresi lambda diperkenalkan pertama kali di Java 8. Tujuan utamanya untuk meningkatkan kekuatan ekspresif bahasa.

Namun, sebelum masuk ke lambda, pertama-tama kita perlu memahami antarmuka fungsional.

Apa itu Antarmuka Fungsional?

Jika antarmuka Java berisi satu dan hanya satu metode abstrak maka itu disebut sebagai antarmuka fungsional. Hanya satu metode ini yang menentukan tujuan antarmuka.

Misalnya, Runnableantarmuka dari paket java.lang; adalah antarmuka fungsional karena hanya terdiri dari satu metode yaitu run().

Contoh 1: Mendefinisikan Antarmuka Fungsional di java

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

Dalam contoh di atas, antarmuka MyInterface hanya memiliki satu metode abstrak getValue (). Oleh karena itu, ini adalah antarmuka fungsional.

Di sini, kami telah menggunakan anotasi @FunctionalInterface. Anotasi memaksa compiler Java untuk menunjukkan bahwa antarmuka adalah antarmuka fungsional. Oleh karena itu, tidak memungkinkan untuk memiliki lebih dari satu metode abstrak. Namun, itu tidak wajib.

Di Java 7, antarmuka fungsional dianggap sebagai Metode Abstrak Tunggal atau jenis SAM . SAM biasanya diimplementasikan dengan Anonymous Classes di Java 7.

Contoh 2: Menerapkan SAM dengan kelas anonim di 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(); ) )

Keluaran :

 Saya baru saja menerapkan Antarmuka Fungsional Runnable.

Di sini, kita bisa melewatkan kelas anonim ke sebuah metode. Ini membantu untuk menulis program dengan lebih sedikit kode di Java 7. Namun, sintaksnya masih sulit dan banyak baris kode tambahan yang diperlukan.

Java 8 memperluas kekuatan SAM dengan melangkah lebih jauh. Karena kita tahu bahwa antarmuka fungsional hanya memiliki satu metode, seharusnya tidak perlu mendefinisikan nama metode itu saat meneruskannya sebagai argumen. Ekspresi Lambda memungkinkan kita melakukan hal itu.

Pengantar ekspresi lambda

Ekspresi Lambda pada dasarnya adalah metode anonim atau tanpa nama. Ekspresi lambda tidak dijalankan sendiri. Sebaliknya, ini digunakan untuk mengimplementasikan metode yang ditentukan oleh antarmuka fungsional.

Bagaimana cara mendefinisikan ekspresi lambda di Jawa?

Berikut adalah cara kita mendefinisikan ekspresi lambda di Java.

 (parameter list) -> lambda body

Operator baru ( ->) yang digunakan dikenal sebagai operator panah atau operator lambda. Sintaksnya mungkin tidak jelas saat ini. Mari jelajahi beberapa contoh,

Misalkan, kami memiliki metode seperti ini:

 double getPiValue() ( return 3.1415; )

Kita bisa menulis metode ini menggunakan ekspresi lambda sebagai:

 () -> 3.1415

Di sini, metode tidak memiliki parameter apa pun. Karenanya, sisi kiri operator menyertakan parameter kosong. Sisi kanan adalah badan lambda yang menentukan tindakan ekspresi lambda. Dalam hal ini, ini mengembalikan nilai 3.1415.

Jenis Tubuh Lambda

Di Jawa, badan lambda terdiri dari dua jenis.

1. Tubuh dengan ekspresi tunggal

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

Jenis tubuh lambda ini dikenal sebagai badan ekspresi.

2. Badan yang terdiri dari blok kode.

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

Jenis tubuh lambda ini dikenal sebagai badan blok. Badan blok memungkinkan badan lambda menyertakan banyak pernyataan. Pernyataan ini diapit di dalam tanda kurung dan Anda harus menambahkan titik koma setelah tanda kurung.

Catatan : Untuk badan blok, Anda bisa memiliki pernyataan pengembalian jika badan mengembalikan nilai. Namun, badan ekspresi tidak memerlukan pernyataan kembali.

Contoh 3: Ekspresi Lambda

Mari kita tulis program Java yang mengembalikan nilai Pi menggunakan ekspresi lambda.

Seperti yang disebutkan sebelumnya, ekspresi lambda tidak dijalankan sendiri. Sebaliknya, itu membentuk implementasi metode abstrak yang ditentukan oleh antarmuka fungsional.

Jadi, kita perlu mendefinisikan antarmuka fungsional terlebih dahulu.

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

Keluaran :

 Nilai Pi = 3,1415

Dalam contoh di atas,

  • Kami telah membuat antarmuka fungsional bernama MyInterface. Ini berisi satu metode abstrak bernamagetPiValue()
  • Di dalam kelas Utama, kami telah menyatakan referensi ke MyInterface. Perhatikan bahwa kita dapat mendeklarasikan referensi dari sebuah antarmuka tetapi kita tidak dapat membuat contoh sebuah antarmuka. Itu adalah,
     // it will throw an error MyInterface ref = new myInterface(); // it is valid MyInterface ref;
  • Kami kemudian menetapkan ekspresi lambda ke referensi.
     ref = () -> 3.1415;
  • Terakhir, kami memanggil metode tersebut getPiValue()menggunakan antarmuka referensi. Kapan
     System.out.println("Value of Pi = " + ref.getPiValue());

Ekspresi Lambda dengan parameter

Sampai sekarang kami telah membuat ekspresi lambda tanpa parameter apa pun. Namun, mirip dengan metode, ekspresi lambda juga dapat memiliki parameter. Sebagai contoh,

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

Kita juga bisa mendefinisikan ekspresi kita sendiri berdasarkan sintaks yang kita pelajari di atas. Ini memungkinkan kita untuk mengurangi baris kode secara drastis seperti yang kita lihat pada contoh di atas.

Artikel yang menarik...