حدد عنصرًا واحدًا
بشكل حدسي، من المؤكد أن تحديد عنصر واحد أسهل من تحديد عناصر متعددة، ولكن هناك بعض المشاكل هنا. دعونا نلقي نظرة أولاً على المشكلة في النهج العام، ثم ننظر إلى كيفية استخدام تعبيرات لامدا لحلها.
لنقم أولاً بإنشاء طريقة جديدة للعثور على عنصر يبدأ بحرف معين، ثم نطبعه.
انسخ رمز الكود كما يلي:
اسم اختيار الفراغ الثابت العام (
أسماء القائمة النهائية <سلسلة>، سلسلة البداية النهائية) {
String FoundName = null;
لـ (اسم السلسلة: الأسماء) {
إذا (name.startsWith(startingLetter)) {
FoundName = name;
استراحة؛
}
}
هذه الطريقة كريهة الرائحة مثل شاحنة القمامة التي مرت للتو. قمنا أولاً بإنشاء متغير FoundName جديد، ثم قمنا بتهيئته ليصبح خاليًا - وهذا هو مصدر الرائحة الكريهة. يتعين علينا التحقق مما إذا كانت فارغة، وإلا فسيتم طرح NullPointerException أو استجابة خطأ. نستخدم أيضًا مكررًا خارجيًا للتنقل خلال القائمة، إذا وجدنا العنصر الذي نريده، فيجب علينا الخروج من الحلقة، مما يضيف إلى الرائحة الأصلية: جنون العظمة من النوع الأساسي، والأسلوب الحتمي، والقابلية للتغيير، كلها تنبض بالحياة. بمجرد الخروج من الحلقة، علينا التحقق من النتائج قبل الطباعة. تتطلب مثل هذه المهمة الصغيرة في الواقع مثل هذا الرمز الطويل.
دعونا نعيد تحليل هذه المسألة. نريد فقط أن نكون قادرين على تحديد العنصر المطابق الأول والتعامل بأمان مع الحالة التي لا يوجد فيها مثل هذا العنصر. دعونا نعيد كتابة طريقةpickName هذه باستخدام تعبير lambda.
انسخ رمز الكود كما يلي:
اسم اختيار الفراغ الثابت العام (
أسماء القائمة النهائية <سلسلة>، سلسلة البداية النهائية) {
Final اختياري<String> FoundName =
الأسماء.الدفق ()
.filter(name ->name.startsWith(startingLetter))
.findFirst();
System.out.println(String.format("اسم يبدأ بـ %s: %s"،
startLetter, FoundName.orElse("لم يتم العثور على اسم")));
}
بعض الوظائف القوية في JDK تجعل هذا الكود موجزًا للغاية. أولاً، نستخدم طريقة التصفية للحصول على جميع العناصر التي تستوفي الشروط، ثم نستخدم طريقة findFirst لفئة الدفق لتحديد العنصر الأول من المجموعة التي تم إرجاعها. تقوم هذه الطريقة بإرجاع كائن اختياري، وهو مزيل الروائح الكريهة المعتمد رسميًا للمتغيرات الخالية في Java.
تعتبر الفئة الاختيارية مفيدة للغاية، فلا داعي للقلق بشأن ما إذا كانت النتيجة موجودة أم لا. إنه ينقذنا من مشكلة استثناءات المؤشر الفارغ ويوضح أنه لا توجد نتيجة هي نتيجة محتملة. من خلال طريقة isPresent()، يمكننا معرفة ما إذا كانت النتيجة موجودة أم لا. إذا أردنا الحصول على قيمة النتيجة، يمكننا استخدام طريقة get(). يمكننا أيضًا تعيين قيمة افتراضية لها باستخدام طريقة orElse (اسم هذه الطريقة سيصدمك)، تمامًا كما في الكود السابق.
نحن نستخدم مجموعة الأصدقاء التي كنا نستخدمها من قبل للتحقق من طريقة اختيارنا.
انسخ رمز الكود كما يلي:
pickName(friends, "N");
pickName(friends, "Z");
يحدد هذا الرمز العنصر المطابق الأول ويطبع رسالة ودية إذا لم يتم العثور عليه.
انسخ رمز الكود كما يلي:
اسم يبدأ بحرف النون: نيت
اسم يبدأ بحرف Z: لم يتم العثور على اسم
يؤدي الجمع بين طريقة findFirst() والفئة Optinal إلى تقليل كمية الكود الخاص بنا ويبدو جيدًا. لكن وظائف الفئة الاختيارية أكثر من ذلك بكثير. على سبيل المثال، بالإضافة إلى توفير قيمة افتراضية عندما لا يكون الكائن موجودًا، يمكنك أيضًا استخدامه لتشغيل جزء من التعليمات البرمجية، أو تعبير لامدا، إذا كانت النتيجة موجودة، مثل هذا:
انسخ رمز الكود كما يلي:
FoundName.ifPresent(name -> System.out.println("Hello " + name));
بالمقارنة مع الكود الحتمي لاختيار الاسم المطابق الأول، يبدو النمط الوظيفي الأنيق للتدفق أفضل. ولكن هل هناك الكثير مما يجب فعله في هذا الإصدار من تدفق المكالمات؟ بالطبع لا، فهذه الأساليب ذكية جدًا وتعمل حسب الطلب (سوف نستكشف هذا بعمق في التقييم البطيء للتدفقات في الصفحة 113).
يُظهر مثال تحديد عنصر واحد وظائف أكثر قوة لمكتبة JDK، فلنلقي نظرة على كيفية قيام تعبيرات lambda بالعثور على القيمة المطلوبة بناءً على المجموعة.