تحويل القائمة
يعد تحويل مجموعة إلى مجموعة جديدة أمرًا بسيطًا مثل التكرار عليها. لنفترض أننا نريد تحويل الأسماء الموجودة في القائمة إلى أحرف كبيرة. دعونا نلقي نظرة على بعض طرق التنفيذ.
السلسلة النصية في Java غير قابلة للتغيير، لذا لا يمكن تغييرها. يمكننا إنشاء سلاسل جديدة لتحل محل العناصر الأصلية في القائمة. ومع ذلك، إذا قمت بذلك، ستختفي القائمة الأصلية؛ قد تكون القائمة الأصلية أيضًا غير قابلة للتغيير، مثل القائمة التي تم إنشاؤها بواسطة Arrays.asList()، لذا لن ينجح تعديل القائمة الأصلية. عيب آخر هو أنه من الصعب العمل بالتوازي.
يعد إنشاء قائمة بأحرف كبيرة جديدة خيارًا جيدًا.
للوهلة الأولى، قد يبدو هذا بمثابة نصيحة ضعيفة؛ فالأداء هو قضية نهتم بها جميعًا. من المثير للدهشة أن البرمجة الوظيفية غالبًا ما تكون أكثر أداءً من البرمجة الحتمية، كما نناقش في مشكلات الأداء في الصفحة 153.
لنبدأ باستخدام هذه المجموعة لإنشاء مجموعة جديدة من الأحرف الكبيرة.
انسخ رمز الكود كما يلي:
Final List<String> UppercaseNames = new ArrayList<String>();
لـ (اسم السلسلة: الأصدقاء) {
UppercaseNames.add(name.toUpperCase());
}
في التعليمات البرمجية الأمرية، نقوم أولاً بإنشاء قائمة فارغة، ثم نملأها بأسماء كبيرة، ونضيف واحدًا تلو الآخر أثناء اجتياز القائمة الأصلية. من أجل التحسين إلى إصدار وظيفي، يمكن أن تكون خطوتنا الأولى هي النظر في استبدال حلقة for بالمكرر الداخلي forEach المذكور في اجتياز القائمة في الصفحة 19، كما هو موضح في المثال التالي.
انسخ رمز الكود كما يلي:
Final List<String> UppercaseNames = new ArrayList<String>();
friends.forEach(name -> UppercaseNames.add(name.toUpperCase()));
System.out.println(uppercaseNames);
نحن نستخدم مكررًا داخليًا، ولكن يتعين علينا أيضًا إنشاء قائمة جديدة وإدراج عناصر فيها. يمكننا أن نتحسن أكثر.
باستخدام تعبيرات لامدا
توجد طريقة خريطة في واجهة البث التي تم تقديمها حديثًا، والتي يمكن أن تساعدنا على الابتعاد عن التباين وجعل التعليمات البرمجية تبدو أكثر إيجازًا. يشبه Steam إلى حد ما مكرر المجموعة، ولكنه يوفر أيضًا وظائف سلسة. باستخدام أساليب هذه الواجهة، يمكننا الجمع بين سلسلة من الاستدعاءات بحيث يُقرأ الكود مثل الترتيب الذي يصف المشكلة، مما يجعله أكثر قابلية للقراءة.
يمكن استخدام طريقة خريطة Steam لتحويل تسلسل الإدخال إلى تسلسل الإخراج - وهو ما يتوافق تمامًا مع ما نريد القيام به.
انسخ رمز الكود كما يلي:
friends.stream()
.map(الاسم -> الاسم.toUpperCase())
.forEach(name -> System.out.print(name + " "));
System.out.println();
تدعم جميع المجموعات في JDK8 طريقة الدفق هذه، والتي تقوم بتغليف المجموعة في مثيل Steam. تستدعي طريقة الخريطة تعبير لامدا المحدد أو كتلة التعليمات البرمجية لكل عنصر في الدفق. تختلف طريقة الخريطة تمامًا عن طريقة forEach، حيث تقوم forEach ببساطة بتنفيذ وظيفة محددة على العناصر الموجودة في المجموعة. تقوم طريقة الخريطة بجمع النتائج الجارية لتعبير لامدا وإرجاع مجموعة النتائج. وأخيرا نقوم بطباعة جميع العناصر باستخدام طريقة forEach.
الأسماء في المجموعة الجديدة كلها بأحرف كبيرة:
انسخ رمز الكود كما يلي:
بريان نيت نيل راجو سارة سكوت
تعد طريقة الخريطة مناسبة جدًا لتحويل مجموعة المدخلات إلى مجموعة مخرجات جديدة. تضمن هذه الطريقة أن يكون لتسلسل الإدخال والإخراج نفس عدد العناصر. ومع ذلك، يمكن أن تكون عناصر الإدخال والإخراج من أنواع مختلفة. في هذا المثال، المدخلات والمخرجات لدينا عبارة عن مجموعة من السلاسل. يمكننا تمرير جزء من التعليمات البرمجية إلى طريقة الخريطة لجعلها تعيد، على سبيل المثال، عدد الأحرف الموجودة في الاسم. في هذه الحالة، لا يزال الإدخال عبارة عن سلسلة من السلاسل، ولكن الإخراج عبارة عن سلسلة من الأرقام، كما يلي.
انسخ رمز الكود كما يلي:
friends.stream()
.map(الاسم -> الاسم.الطول())
.forEach(count -> System.out.print(count + " "));
والنتيجة هي عدد الحروف في كل اسم:
انسخ رمز الكود كما يلي:
5 4 4 4 4 5
يتم استخدام إصدار أحدث من تعبير لامدا لتجنب عمليات التعديل الصريحة؛ وهذا الكود موجز للغاية. الكتابة بهذه الطريقة لم تعد تتطلب تهيئة مجموعة فارغة ومتغير البيانات المهملة؛ هذا المتغير مخفي في التنفيذ الأساسي.
مرجع طريقة الاستخدام
يمكننا أيضًا استخدام مراجع الطريقة لجعلها أكثر إيجازًا. عندما يلزم تمرير تنفيذ واجهة وظيفية، يمكن لمترجم Java قبول تعبيرات lambda أو مراجع الأساليب. باستخدام هذه الميزة، يمكنك استبدال name -> name.toUpperCase() بـ String::toUpperCase، كما يلي:
انسخ رمز الكود كما يلي:
friends.stream()
.map(سلسلة::toUpperCase)
.forEach(name -> System.out.println(name));
عندما يتم تمرير المعلمات إلى الطريقة التي تم إنشاؤها - تنفيذ الطريقة المجردة للواجهة الوظيفية - ستستدعي Java طريقة toUpperCase لمعلمة السلسلة. مرجع المعلمة هذا مخفي هنا. في سيناريو بسيط مثل السيناريو أعلاه، يمكننا استخدام مراجع الأساليب لاستبدال تعبيرات لامدا؛ لمزيد من المعلومات، راجع متى يجب استخدام مراجع الأساليب في الصفحة 26.
انسخ رمز الكود كما يلي:
سأل أحد الأصدقاء:
متى يجب عليك استخدام مراجع الطريقة؟
عند البرمجة بلغة Java، نستخدم عادةً تعبيرات lambda أكثر بكثير من مراجع الأساليب. ولكن هذا لا يعني أن مراجع الطريقة غير مهمة أو عديمة الفائدة. عندما تكون تعبيرات لامدا قصيرة جدًا، فهي بديل جيد لاستدعاء أساليب المثيل أو الأساليب الثابتة مباشرةً. بمعنى آخر، إذا كان تعبير لامدا يمرر المعلمات إلى استدعاء الطريقة فقط، فيجب علينا استخدام مراجع الطريقة بدلاً من ذلك.
إن تعبير لامدا مثل هذا يشبه إلى حد ما ما قاله توم سميكوفسكي في فيلم "العمل مع خطأ"، وتتمثل مهمته في "جلب المتطلبات من العملاء إلى مهندسي البرمجيات". ولهذا السبب، أسمي هذا النمط من أسلوب إعادة البناء مرجعًا لنمط الدودة.
بالإضافة إلى كونها موجزة، فإن استخدام مراجع الطريقة يمكن أن يعكس بشكل أفضل معنى ووظيفة اسم الطريقة نفسه.
خلف استخدام مراجع الطريقة، يلعب المترجم دورًا رئيسيًا. سيتم اشتقاق الكائن الهدف والمعلمات المشار إليها بواسطة الطريقة من المعلمات التي تم تمريرها في الطريقة التي تم إنشاؤها. يتيح لك هذا استخدام مراجع الطريقة لكتابة تعليمات برمجية أكثر إيجازًا من استخدام تعبيرات لامدا. ومع ذلك، إذا كان سيتم تعديل المعلمات قبل تمريرها إلى الطريقة أو إرجاع نتيجة الاستدعاء، فلا يمكننا استخدام طريقة الكتابة الملائمة هذه.
في المثال السابق، يشير مرجع الطريقة إلى طريقة مثيل. يمكن أن تشير مراجع الطريقة أيضًا إلى طريقة ثابتة وطريقة تقبل المعلمات. وسنرى أمثلة على ذلك لاحقا.
يمكن أن تساعدنا تعبيرات Lambda في اجتياز المجموعات وتحويل المجموعات. كما سنرى أدناه، فهو يساعدنا أيضًا على تحديد عنصر بسرعة من المجموعة.