عبارت های لامبدا در جاوا — راهنمای کاربردی
پیش از آنکه پشتیبانی از عبارتهای لامبدا در نسخه JDK8 به جاوا اضافه شود، ما تنها در زبانهایی مانند #C و ++C از آنها استفاده کرده بودیم. اینک که این قابلیت به جاوا اضافه شده است باید نگاهی دقیقتر به آنها بیندازیم. اضافه شدن عبارت های لامبدا در جاوا موجب اضافه شدن عناصر ساختاری دیگری به این زبان شده است که توان بیان عبارتها را در جاوا بالا برده است. در این مقاله میخواهیم روی مبانی مقدماتی که برای آغاز کار با عبارتهای لامبدا در کدهای مدرن نیاز دارید تمرکز کنیم.
مقدمه
عبارتهای لامبدا از مزیت ظرفیتهای پردازش موازی محیطهای چند نخی چنان که در پشتیبانی از عملیات pipeline روی دادهها در API Stream دیدهایم استفاده میکنند. برخی متدهای بینام وجود دارند که برای پیادهسازی متد تعریف شده از سوی یک اینترفیس تابعی استفاده میشوند. پیش از آشنا شدن با عبارتهای لامبدا باید با مفهوم اینترفیس تابعی آشنا شوید.
اینترفیسهای تابعی
اینترفیس تابعی اینترفیسی است که شامل یک و تنها یک متد مجرد است. اگر نگاهی به تعریف اینترفیس Runnable استاندارد جاوا بکنید، متوجه خواهید شد که در تعریف اینترفیس تابعی قرار میگیرد، زیرا تنها یک متد یعنی ()run را تعریف میکند. در قطعه کد نمونه زیر متد computeName به صراحت مجرد است و تنها متد تعریف شده است که موجب میشود MyName یک اینترفیس تابعی باشد.
1interface MyName{
2 String computeName(String str);
3}
عملگر arrow
عبارتهای لامبدا عملگر جدید arrow را به صورت (<-) در جاوا معرفی کردهاند. و این عملگر عبارت لامبدا را به دو بخش تقسیم میکند:
(n) -> n*n
سمت چپ پارامترهای مورد نیاز عبارت را تعیین میکند که در صورت عدم نیاز به پارامتر میتواند خالی هم باشد. سمت راست بدنه لامبدا است که اقدامات عبارت لامبدا را تعیین میکند. این عملگر را میتوان به صورت «تبدیل میشود» ترجمه کرد. برای نمونه در مثال فوق «n تبدیل میشود به n*n» یا «n تبدیل میشود به جذر n.» با استفاده از اینترفیس تابعی و عملگر arrow میتوانید یک عبارت لامبدای ساده را کنار هم قرار دهید:
1interface NumericTest {
2 boolean computeTest(int n);
3}
4
5public static void main(String args[]) {
6 NumericTest isEven = (n) -> (n % 2) == 0;
7 NumericTest isNegative = (n) -> (n < 0);
8
9 // Output: false
10 System.out.println(isEven.computeTest(5));
11
12 // Output: true
13 System.out.println(isNegative.computeTest(-5));
14}
لامبدای خوش آمدگویی
1interface MyGreeting {
2 String processName(String str);
3}
4
5public static void main(String args[]) {
6 MyGreeting morningGreeting = (str) -> "Good Morning " + str + "!";
7 MyGreeting eveningGreeting = (str) -> "Good Evening " + str + "!";
8
9 // Output: Good Morning Luis!
10 System.out.println(morningGreeting.processName("Luis"));
11
12 // Output: Good Evening Jessica!
13 System.out.println(eveningGreeting.processName("Jessica"));
14}
متغیرهای morningGreeting و eveningGreeting در خطوط 6 و 7 فوق ارجاعی به اینترفیس MyGreeting دارند و عبارتهای خوشامدگویی مختلفی را تعریف میکنند. زمانی که یک عبارت لامبدا مینویسیم امکان تعیین صریح نوع پارامتر در عبارت به صورت زیر نیز وجود دارد:
1MyGreeting morningGreeting = (String str) -> "Good Morning " + str + "!";
2MyGreeting eveningGreeting = (String str) -> "Good Evening " + str + "!";
عبارتهای لامبدای بلوکی
تا به اینجا، نمونههایی از لامبداهای عبارت منفرد را مورد بررسی قرار دادیم. نوع دیگری از عبارت نیز وجود دارد که هنگامی استفاده میشود که کد سمت راست عملگر arrow شامل بیش از یک گزاره باشد که به نام «لامبدای بلوکی» (block lambdas) شناخته میشود:
1interface MyString {
2 String myStringFunction(String str);
3}
4
5public static void main (String args[]) {
6 // Block lambda to reverse string
7 MyString reverseStr = (str) -> {
8 String result = "";
9
10 for(int i = str.length()-1; i >= 0; i--)
11 result += str.charAt(i);
12
13 return result;
14 };
15
16 // Output: omeD adbmaL
17 System.out.println(reverseStr.myStringFunction("Lambda Demo"));
18}
اینترفیسهای تابعی ژنریک
عبارت لامبدا نمیتواند ژنریک باشد. اما اینترفیس تابعی مرتبط با عبارت لامبدا میتواند چنین باشد. امکان نوشتن یک اینترفیس تابعی و مدیریت انواع بازگشتی مختلف به صورت زیر وجود دارد:
1interface MyGeneric<T> {
2 T compute(T t);
3}
4
5public static void main(String args[]){
6
7 // String version of MyGenericInteface
8 MyGeneric<String> reverse = (str) -> {
9 String result = "";
10
11 for(int i = str.length()-1; i >= 0; i--)
12 result += str.charAt(i);
13
14 return result;
15 };
16
17 // Integer version of MyGeneric
18 MyGeneric<Integer> factorial = (Integer n) -> {
19 int result = 1;
20
21 for(int i=1; i <= n; i++)
22 result = i * result;
23
24 return result;
25 };
26
27 // Output: omeD adbmaL
28 System.out.println(reverse.compute("Lambda Demo"));
29
30 // Output: 120
31 System.out.println(factorial.compute(5));
32
33}
عبارت لامبدا به عنوان آرگومان
یکی از استفادههای رایج از لامبداها برای ارسال آنها به صورت آرگومان است. میتوان از آنها در هر قطعه کدی که یک نوع هدف ارائه میکند استفاده کرد. این وضعیت کاربردهای جالبی دارد، زیرا امکان ارسال کد قابل اجرا را به عنوان آرگومان به متدها فراهم میکند. برای ارسال عبارت لامبدا به صورت پارامتر، باید مطمئن شوید که نوع اینترفیس تابعی با پارامتر مورد نیاز مطابقت دارد:
1interface MyString {
2 String myStringFunction(String str);
3}
4
5public static String reverseStr(MyString reverse, String str){
6 return reverse.myStringFunction(str);
7}
8
9public static void main (String args[]) {
10 // Block lambda to reverse string
11 MyString reverse = (str) -> {
12 String result = "";
13
14 for(int i = str.length()-1; i >= 0; i--)
15 result += str.charAt(i);
16
17 return result;
18 };
19
20 // Output: omeD adbmaL
21 System.out.println(reverseStr(reverse, "Lambda Demo"));
22}
سخن پایانی
مفاهیمی که در این مقاله بررسی کردیم، یک نقطه شروع مناسب برای یادگیری عبارتهای لامبدای جاوا در اختیار شما قرار میدهند. بدین ترتیب، میتوانید کدهای خود را بررسی کنید تا ببیند کجا قادر هستید توان کدنویسی جاوا را افزایش دهید.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای جاوا (Java)
- مجموعه آموزشهای برنامهنویسی
- گنجینه آموزش های جاوا (Java)
- عبارتهای لامبدا (lambda) در جاوا ۸ — مرور سریع
- تابعهای لامبدا (Lambda) در پایتون — راهنمای مقدماتی
==