3 سال پیش / خواندن دقیقه

آموزش عبارات لامبدا در جاوا (Lambda Expressions) + مثال

آموزش عبارات لامبدا در جاوا (Lambda Expressions) + مثال

در این آموزش ، در مورد ویژگی جدید معرفی شده در جاوا ۸ ، یعنی پشتیبانی از عبارات لامبدا با استفاده از رابط کاربری خواهید آموخت.

هنگام انتشار جاوا ۸ ، عبارات لامبدا موضوع داغی بود. عبارات لامبدا در JDK نسخه ۸ اضافه شده است تا با افزایش قدرت بیان زبان ، عملکرد جاوا را تقویت کنید.

اما ، قبل از ورود به لامبدا ، ابتدا باید بدانیم که رابط کاربری چیست.

رابط کاربری یا اینترفیس چیست؟

اگر یک اینترفیس جاوا شامل فقط یک متد انتزاعی(abstract) باشد ، آن را اینترفیس تابعی می نامند. به عنوان مثال ، اینترفیس Runnable از پکیج ؛java.lang یک اینترفیس تابعی است زیرا تنها یک متد یعنی ()run را تشکیل می دهد.

مثال ۱ : یک رابط کاربری یا اینترفیس در جاوا تعریف کنید

import java.lang.FunctionalInterface;
@FunctionalInterface
public interface MyInterface{
double getValue();
}

توجه: حاشیه نویسی FunctionalInterface@ ضروری نیست ، اما استفاده از آن عاقلانه است زیرا کامپایلر جاوا را وادار می کند که اینترفیس تعریف شده اینترفیس تابعی باشد و فقط باید یک متد انتزاعی داشته باشد. در جاوا ۷ ، به اینترفیس Abstract Method Single یا SAM type گفته می شد.

SAM معمولاً با کلاس های ناشناس در جاوا ۷ اجرا می شد.

مثال ۲: SAM را با کلاس های ناشناس در جاوا اجرا کنید

public class FunctionInterfaceTest {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(“I just implemented the Runnable Functional Interface.”);
}
}).start();
}
}

امکان ارسال یک کلاس ناشناس به سازنده یا متد ، نوشتن کد جاوا ۷ را با فایل های کمتری آسان کرد. با این حال ، ساختار همچنان دشوار و کد بسیاری مورد نیاز بود.

جاوا ۸ با یک قدم جلوتر رفتن ، قدرت یک SAM را افزایش داد. از آنجا که می دانیم اینترفیس فقط یک متد دارد ، نیازی به تعریف نام آن متد در هنگام ارسال آن به عنوان آرگومان نیست. عبارت لامبدا به ما امکان می دهد دقیقاً همین کار را انجام دهیم.

آشنایی با عبارت لامبدا

عبارت لامبدا در اصل متدی ناشناس یا نامشخص است و به تنهایی اجرا نمی شود. در عوض ، از آن برای پیاده سازی متد تعریف شده توسط اینترفیس استفاده می شود.

چگونه عبارت لامبدا را در جاوا تعریف کنیم؟

عبارت لامبدا یک عنصر نحوی جدید و اپراتور را به زبان جاوا معرفی می کند. به اپراتور جدید عملگر لامبدا یا عملگر پیکان گفته می شود. (->)

بیایید یک متد ساده بنویسیم که فقط یک مقدار ثابت double را برگرداند.

double getPiValue() { return 3.1415; }

عبارت لامبدا معادل متد فوق عبارت است از:

() -> 3.1415

در عبارت لامبدا ، سمت چپ عبارت پارامترهای موردنیاز عبارت را مشخص می کند ، در حالی که سمت راست بدنه ی لامبدا است ، که عملکرد عبارت لامبدا را مشخص می کند.

بدنه لامبدا از دو نوع است.

۱- بدنه با یک عبارت واحد

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

۲- بدنه تشکیل شده از یک بلوک کد

() -> {

double pi = 3.1415;

return pi;

}

یک عبارت لامبدا می تواند پارامتر داشته باشد.مثلا :

(n) -> (n%2)==0

این عبارت لامبدا مشخص می کند که مقدار n زوج یا فرد است.

اگر بدنه ی لامبدا یک بلوک کد است ، همیشه باید یک مقدار را برگردانید. اما ، اگر بدنه ی لامبدا فقط یک عبارت است ، مقدار بازگشتی لازم نیست.

بیایید کد جاوا را با عبارت لامبدا بنویسیم که مقدار Pi را بر می گرداند.

همانطور که قبلا ذکر شد ، عبارت لامبدا به تنهایی اجرا نمی شود. در عوض ، اجرای متد انتزاعی تعریف شده توسط اینترفیس تابعی را تشکیل می دهد.

مثال ۳ : عبارت لامبدا را با رابط کاربری(اینترفیس) در جاوا تعریف کنید

در ابتدا باید یک رابط کاربری MyInterface.java تعریف کنیم:

import java.lang.FunctionalInterface;
// This is functional interface
@FunctionalInterface
public interface MyInterface{
double getPiValue();
}

حال ، عبارت لامبدا را به عنوان مثال اینترفیس تابعی اختصاص می دهیم.

public class LambdaMain {
public static void main( String[] args ) {
MyInterface myInterface;
myInterface = () -> 3.1415;
System.out.println(“Value of Pi = ” + myInterface.getPiValue());
}
}

خروجی برابر است با:

Value of Pi = 3.1415

عبارت لامبدا باید با متد انتزاعی سازگار باشد. یعنی اگر () -> “۳٫۱۴۱۵” را به نمونه myInterface اختصاص دهید ، کد ایراد دارد و اجرا نخواهد شد زیرا طبق تعریف در اینترفیس، نوع رشته با double سازگار نیست.

شما احتمالا از یک عبارت لامبدا مانند کد بالا در یک برنامه واقعی استفاده نمی کنید. بیایید به مثال دیگری از عبارت لامبدا که پارامتر می گیرد نگاهی بیندازیم.

مثال ۴ : استفاده از عبارت لامبدا با پارامترهای موجود در جاوا

@FunctionalInterface
interface MyInterface {
String reverse(String n);
}
public class ParamLambdaMain {
public static void main( String[] args ) {
MyInterface myInterface = (str) -> {
String result = “”;
for (int i = str.length()-1; i >= 0 ; i–)
result += str.charAt(i);
return result;
};
System.out.println(“Lambda reversed = ” + myInterface.reverse(“Lambda”));
}
}

خروجی

Lambda reversed = adbmaL

اینترفیس تابعی عمومی

اینترفیس بالا فقط String را می پذیرد و شی String را برمی گرداند. با این حال ، ما می توانیم رابط کاربری عمومی ایجاد کنیم، به طوری که هر نوع داده پذیرفته شود.

مثال ۵ : چگونه رابط کاربری می تواند هر نوع داده را در جاوا بپذیرد؟

بیایید ببینیم که چگونه این کار انجام شده است:

// GenericInterface.java
@FunctionalInterface
interface GenericInterface<T> {
T func(T t);
}

حال ، GenericInterface با هر عبارت لامبدا که یک پارامتر را می گیرد سازگار است و مقدار همان نوع را بر می گرداند.

// GenericLambda.java
public class GenericLambda {
public static void main( String[] args ) {
GenericInterface<String> 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”));
GenericInterface<Integer> 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));
}
}

خروجی

Lambda reversed = adbmaL

factorial of 5 = 120

عبارت لامبدا و جریان API

پکیج جدید java.util.stream به JDK8 اضافه شده است که به برنامه نویسان java اجازه می دهد تا عملیاتی مانند search ، filter ، map ، reduce یا در غیر این صورت دستکاری مجموعه ها مانند لیست ها را انجام دهند.

به عنوان مثال ، یک جریان داده (یک لیست رشته) داریم که در آن هر رشته ترکیبی از نام کشور و محل کشور است. اکنون ، می توانیم این جریان داده را پردازش کنیم و فقط مکان های نپال را بازیابی کنیم.

مثال ۶ : نمایش استفاده از لامبدا با جریان API

import java.util.ArrayList;
import java.util.List;
public class StreamMain {
static List<String> places = new ArrayList<>();
// preparing our data
public static List getPlaces(){
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<String> 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));
}
}

خروجی

Places from Nepal:

NEPAL, KATHMANDU

NEPAL, POKHARA

جریان API به ما امکان دسترسی به متد هایی مانند ()filter() ، map و ()forEach را می دهد که می توانند یک عبارت لامبدا را به عنوان ورودی در نظر بگیرند. ما می توانیم از هر دو متد داخلی جاوا استفاده کنیم و همچنین عبارات خاص خود را بر اساس نحوی که در بالا آموخته ایم تعریف کنیم. این کار باعث می شود خطوط کد را همانطور که در مثال بالا دیدیم به طرز چشمگیری کاهش یابد.


شاید از نوشته‌های زیر خوشتان بیاید
نظر خود را درباره این پست بنویسید ...

منوی سریع