آموزش عبارات لامبدا در جاوا (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;
}
یک عبارت لامبدا می تواند پارامتر داشته باشد.مثلا :
جاوا، جاوا اسکریپت رو قورت بده! بدون کلاس، سرعت 2 برابر، ماندگاری 3 برابر، پولسازی عالی با توسعه وب، ماشین لرنینگ و ... کتابخانه های پیشرفته جاوا اسکریپت و ... دانلود:
(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 را می دهد که می توانند یک عبارت لامبدا را به عنوان ورودی در نظر بگیرند. ما می توانیم از هر دو متد داخلی جاوا استفاده کنیم و همچنین عبارات خاص خود را بر اساس نحوی که در بالا آموخته ایم تعریف کنیم. این کار باعث می شود خطوط کد را همانطور که در مثال بالا دیدیم به طرز چشمگیری کاهش یابد.
سلام، سه تابع نوشتم که هم در aws آمازون ذخیره شده و هم به صورت ایمج در هاب داکر. و مجموع اونها یک استرینگ و یک الگو از ورودی میگیرند و به عنوان خروجی تعدادی از الگوهای رشته ورودی رو حذف میکنند
پاسخچه جوری میتونم یک زمانبند طراحی کنم که اگر تعداد ورودیها زیر 10 تا بود از داکر و اگر 10 تا یا بیشتر بود از aws استفاده کنه؟