كيف تبدأ العمل مع تعبيرات Lambda في Java

قبل إضافة دعم تعبيرات Lambda بواسطة JDK 8 ، كنت أستخدم أمثلة منها فقط بلغات مثل C # و C ++.

بمجرد إضافة هذه الميزة إلى Java ، بدأت في النظر إليها عن كثب.

تضيف إضافة تعبيرات lambda عناصر بناء الجملة التي تزيد من القوة التعبيرية لجافا. في هذه المقالة ، أود التركيز على المفاهيم الأساسية التي تحتاج إلى التعرف عليها حتى تتمكن من البدء في إضافة تعبيرات لامدا إلى الكود الخاص بك اليوم.

مقدمة سريعة

تستفيد تعبيرات Lambda من إمكانات العملية المتوازية للبيئات متعددة النواة كما يظهر من خلال دعم عمليات خطوط الأنابيب على البيانات في Stream API.

إنها طرق مجهولة (طرق بدون أسماء) تستخدم لتنفيذ طريقة محددة بواسطة واجهة وظيفية. من المهم أن تعرف ما هي الواجهة الوظيفية قبل أن تتسخ يديك بتعابير لامدا.

واجهة وظيفية

الواجهة الوظيفية هي واجهة تحتوي على طريقة مجردة واحدة فقط.

إذا كنت تأخذ نظرة على تعريف واجهة جافا القياسية Runnable، ستلاحظ كيف أن تقع في تعريف من واجهة وظيفية لأنه يعرف إلا أسلوب واحد: run().

في نموذج التعليمات البرمجية أدناه ، الطريقة computeNameمجردة ضمنيًا وهي الطريقة الوحيدة المحددة ، مما يجعل MyName واجهة وظيفية.

interface MyName{ String computeName(String str); }

مشغل السهم

تقدم تعبيرات Lambda عامل السهم الجديد ->إلى Java. يقسم تعبيرات لامدا إلى جزئين:

(n) -> n*n

يحدد الجانب الأيسر المعلمات التي يتطلبها التعبير ، والتي يمكن أن تكون فارغة أيضًا إذا لم تكن هناك حاجة إلى معلمات.

الجانب الأيمن هو جسم لامدا الذي يحدد أفعال تعبير لامدا. قد يكون من المفيد التفكير في هذا العامل على أنه "يصبح". على سبيل المثال ، "n تصبح n * n" ، أو "n تصبح n تربيع".

مع وضع مفاهيم الواجهة الوظيفية ومشغل الأسهم في الاعتبار ، يمكنك تجميع تعبير لامدا بسيط:

interface NumericTest { boolean computeTest(int n); } public static void main(String args[]) { NumericTest isEven = (n) -> (n % 2) == 0; NumericTest isNegative = (n) -> (n < 0); // Output: false System.out.println(isEven.computeTest(5)); // Output: true System.out.println(isNegative.computeTest(-5)); }
interface MyGreeting { String processName(String str); } public static void main(String args[]) { MyGreeting morningGreeting = (str) -> "Good Morning " + str + "!"; MyGreeting eveningGreeting = (str) -> "Good Evening " + str + "!"; // Output: Good Morning Luis! System.out.println(morningGreeting.processName("Luis")); // Output: Good Evening Jessica! System.out.println(eveningGreeting.processName("Jessica")); }

المتغيرات morningGreetingو eveningGreeting، خطوط 6 و 7 في العينة أعلاه، تجعل إشارة إلى MyGreetingواجهة وتحديد التعابير تحية مختلفة.

عند كتابة تعبير لامدا ، من الممكن أيضًا تحديد نوع المعلمة بشكل صريح في التعبير مثل هذا:

MyGreeting morningGreeting = (String str) -> "Good Morning " + str + "!"; MyGreeting eveningGreeting = (String str) -> "Good Evening " + str + "!";

كتلة تعبيرات لامدا

حتى الآن ، قمت بتغطية عينات من لامبدا ذات التعبير الفردي. هناك نوع آخر من التعبيرات المستخدمة عندما يحتوي الكود الموجود على الجانب الأيمن من عامل السهم على أكثر من عبارة واحدة تُعرف باسم block lambdas :

interface MyString { String myStringFunction(String str); } public static void main (String args[]) { // Block lambda to reverse string MyString reverseStr = (str) -> { String result = ""; for(int i = str.length()-1; i >= 0; i--) result += str.charAt(i); return result; }; // Output: omeD adbmaL System.out.println(reverseStr.myStringFunction("Lambda Demo")); }

واجهات وظيفية عامة

لا يمكن أن يكون تعبير لامدا عامًا. ولكن يمكن للواجهة الوظيفية المرتبطة بتعبير لامدا. من الممكن كتابة واجهة عامة واحدة والتعامل مع أنواع مختلفة من الإرجاع مثل هذا:

interface MyGeneric { T compute(T t); } public static void main(String args[]){ // String version of MyGenericInteface MyGeneric reverse = (str) -> { String result = ""; for(int i = str.length()-1; i >= 0; i--) result += str.charAt(i); return result; }; // Integer version of MyGeneric MyGeneric factorial = (Integer n) -> { int result = 1; for(int i=1; i <= n; i++) result = i * result; return result; }; // Output: omeD adbmaL System.out.println(reverse.compute("Lambda Demo")); // Output: 120 System.out.println(factorial.compute(5)); }

تعبيرات لامدا كوسيطات

أحد الاستخدامات الشائعة لللامدا هو تمريرها كحجج.

يمكن استخدامها في أي جزء من التعليمات البرمجية التي توفر نوع الهدف. أجد هذا مثيرًا ، حيث يتيح لي تمرير التعليمات البرمجية القابلة للتنفيذ كوسيطات للطرق.

لتمرير تعبيرات lambda كمعلمات ، فقط تأكد من أن نوع الواجهة الوظيفية متوافق مع المعلمة المطلوبة.

interface MyString { String myStringFunction(String str); } public static String reverseStr(MyString reverse, String str){ return reverse.myStringFunction(str); } public static void main (String args[]) { // Block lambda to reverse string MyString reverse = (str) -> { String result = ""; for(int i = str.length()-1; i >= 0; i--) result += str.charAt(i); return result; }; // Output: omeD adbmaL System.out.println(reverseStr(reverse, "Lambda Demo")); }

ستمنحك هذه المفاهيم أساسًا جيدًا لبدء العمل مع تعبيرات لامدا. ألقِ نظرة على التعليمات البرمجية الخاصة بك وشاهد أين يمكنك زيادة القوة التعبيرية لجافا.