البرمجة الوظيفية في Java: من لامدا إلى Stream API

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

البرمجة الوظيفية في Java: من تعبيرات Lambda إلى Stream API



البرمجة الوظيفية (FP) هي نموذج يتم فيه تمثيل العمليات الحسابية كتقييم للدوال الرياضية، مما يتجنب تغييرات الحالة وتحوير البيانات. لفترة طويلة، بقيت Java لغة موجهة للكائنات بشكل صارم، ولكن مع إصدار Java 8 (2014)، اتخذت خطوة كبيرة نحو البرمجة الوظيفية بإضافة تعبيرات lambda والواجهات الوظيفية و Stream API. اليوم، هذه الأدوات لا غنى عنها لكتابة كود موجز وقابل للقراءة وآمن في التعامل مع الخيوط.



في هذه المقالة، سنقوم بتحليل المفاهيم الأساسية للبرمجة الوظيفية في Java: من أساسيات lambdas إلى معالجة المجموعات المتقدمة باستخدام Stream API. المادة موجهة للمطورين الذين هم على دراية بالفعل ببناء جملة Java الأساسية ولكنهم يرغبون في إتقان الأساليب الحديثة.



1. تعبيرات Lambda والواجهات الوظيفية



تعبير lambda هو دالة مجهولة (دالة بدون اسم) يمكن تمريرها كوسيط أو تخزينها في متغير. في Java، تقوم lambda بتنفيذ واجهة وظيفية — وهي واجهة تحتوي على طريقة مجردة واحدة بالضبط (SAM — Single Abstract Method).



بناء الجملة:

(parameters) -> { body }


مثال: بدلاً من إنشاء فئة مجهولة للمقارن:

// Old way (Java 7)Comparator<String> comparator = new Comparator<String>() {    @Override    public int compare(String s1, String s2) {        return s1.length() - s2.length();    }};

// New way (Java 8+)Comparator<String> comparatorLambda = (s1, s2) -> s1.length() - s2.length();


الواجهات الوظيفية الرئيسية في Java (الحزمة java.util.function):

  • Predicate<T> — تتحقق من شرط (طريقة test).
  • Function<T, R> — تحول كائن من النوع T إلى R (طريقة apply).
  • Consumer<T> — تنفذ إجراءً على كائن (طريقة accept).
  • Supplier<T> — تزود بكائن بدون معلمات إدخال (طريقة get).


مثال مع Predicate:

Predicate<Integer> isEven = n -> n % 2 == 0;System.out.println(isEven.test(4)); // trueSystem.out.println(isEven.test(5)); // false


مراجع الطرق (Method References) هي ترميز مختصر لـ lambda عندما يتكون الجسم من استدعاء طريقة واحدة:

// Lambdalist.forEach(item -> System.out.println(item));// Method Referencelist.forEach(System.out::println);


2. Stream API: العمليات الأساسية



Stream API هي أداة قوية لمعالجة تسلسلات البيانات (المجموعات، المصفوفات، الملفات) بأسلوب تصريحي. Stream لا يخزن البيانات؛ بل يصف فقط خط أنابيب من العمليات. لا يتم تعديل البيانات — كل خطوة تنشئ stream جديد.



إنشاء Stream:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");Stream<String> stream = names.stream(); // sequentialStream<String> parallelStream = names.parallelStream(); // parallel


العمليات الوسيطة (ترجع Stream جديد):

  • filter(Predicate) — تختار العناصر بناءً على شرط.
  • map(Function) — تحول كل عنصر.
  • sorted() / sorted(Comparator) — الترتيب.
  • distinct() — تزيل التكرارات.
  • limit(n) — تحد من عدد العناصر.


العمليات الطرفية (تنهي الـ stream، ترجع نتيجة):

  • collect(Collectors.toList()) — تجمع في مجموعة.
  • forEach(Con

المدونات

توصيات الكتب