الدوال — المتقدمة

في هذا الدرس، سنتعلم المفاهيم المتقدمة للدوال في Java.

الدوال المتكررة (Recursion)

الدالة المتكررة هي دالة تستدعي نفسها.

مثال: المضروب

JAVA
public static int factorial(int n) {
    if (n <= 1) return 1;  // الحالة الأساسية
    return n * factorial(n - 1);  // الاستدعاء الذاتي
}

// الاستدعاء
System.out.println(factorial(5));  // 120 (5 × 4 × 3 × 2 × 1)
▶ جرّب الكود

كيف يعمل؟

TEXT
factorial(5)
= 5 * factorial(4)
= 5 * 4 * factorial(3)
= 5 * 4 * 3 * factorial(2)
= 5 * 4 * 3 * 2 * factorial(1)
= 5 * 4 * 3 * 2 * 1
= 120

مثال: متتالية فيبوناتشي

JAVA
public static int fibonacci(int n) {
    if (n <= 0) return 0;
    if (n == 1) return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// الاستدعاء
for (int i = 0; i < 10; i++) {
    System.out.print(fibonacci(i) + " ");  // 0 1 1 2 3 5 8 13 21 34
}
▶ جرّب الكود

⚠️ تحذير: Stack Overflow

JAVA
// ❌ دالة متكررة بدون حالة أساسية
public static void infinite() {
    infinite();  // ستؤدي إلى Stack Overflow
}

Lambda Expressions (Java 8+)

Lambda expressions هي طريقة مختصرة لكتابة دوال مجهلة.

صيغة Lambda

JAVA
(معلمات) -> جسم_الدالة

أمثلة

JAVA
// دالة عادية
public static int add(int a, int b) {
    return a + b;
}

// Lambda
(a, b) -> a + b

// Lambda مع نوع البيانات
(int a, int b) -> a + b

// Lambda مع جسم متعدد
(a, b) -> {
    int sum = a + b;
    return sum;
}

استخدام Lambda مع ArrayList

JAVA
import java.util.ArrayList;
import java.util.Arrays;

public class LambdaDemo {
    public static void main(String[] args) {
        ArrayList<String> names = new ArrayList<>(Arrays.asList("أحمد", "محمد", "علي"));
        
        // forEach مع Lambda
        names.forEach(name -> System.out.println(name));
        
        // removeIf مع Lambda
        names.removeIf(name -> name.startsWith("أ"));
        System.out.println(names);  // [محمد، علي]
    }
}

Lambda مع Interfaces

JAVA
@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);
}

public class LambdaInterfaceDemo {
    public static void main(String[] args) {
        Calculator add = (a, b) -> a + b;
        Calculator subtract = (a, b) -> a - b;
        Calculator multiply = (a, b) -> a * b;
        
        System.out.println(add.calculate(5, 3));      // 8
        System.out.println(subtract.calculate(5, 3));  // 2
        System.out.println(multiply.calculate(5, 3));  // 15
    }
}

الدوال عالية الدالة (Higher-Order Functions)

الدوال عالية الدالة هي دوال تأخذ دوال كمعلمات أو تُرجع دوال.

مثال: تصفية المصفوفة

JAVA
import java.util.ArrayList;
import java.util.Arrays;

public class HigherOrderDemo {
    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
        
        // تصفية الأرقام الزوجية
        ArrayList<Integer> evenNumbers = filter(numbers, n -> n % 2 == 0);
        System.out.println(evenNumbers);  // [2, 4, 6, 8, 10]
        
        // تصفية الأرقام الكبرى من 5
        ArrayList<Integer> largeNumbers = filter(numbers, n -> n > 5);
        System.out.println(largeNumbers);  // [6, 7, 8, 9, 10]
    }
    
    public static ArrayList<Integer> filter(ArrayList<Integer> list, 
                                            java.util.function.Predicate<Integer> condition) {
        ArrayList<Integer> result = new ArrayList<>();
        for (int num : list) {
            if (condition.test(num)) {
                result.add(num);
            }
        }
        return result;
    }
}
▶ جرّب الكود

Method References (Java 8+)

Method references هي اختصار لـ Lambda:

JAVA
import java.util.ArrayList;
import java.util.Arrays;

public class MethodRefDemo {
    public static void main(String[] args) {
        ArrayList<String> names = new ArrayList<>(Arrays.asList("أحمد", "محمد", "علي"));
        
        // Lambda
        names.forEach(name -> System.out.println(name));
        
        // Method Reference (نفس النتيجة)
        names.forEach(System.out::println);
    }
}

❓ أسئلة شائعة

س متى أستخدم الدوال المتكررة بدلاً من الحلقات؟
ج استخدم الدوال المتكررة عندما يكون للمشكلة طبيعة متكررة (مثل الأشجار، الأبراج). الحلقات أكثر كفاءة للمشاكل البسيطة.
س ما هو @FunctionalInterface؟
ج annotation يدل على أن الواجهة تحتوي على طريقة مجردة واحدة فقط. هذا ضروري لاستخدام Lambda.
س هل Lambda أفضل من الدوال العادية؟
ج Lambda أكثر اختصارًا للدوال البسيطة. للدوال المعقدة، الدوال العادية أكثر وضوحًا.

📖 ملخص

📝 تمارين

  1. متكرر: اكتب دالة متكررة لحساب أس عدد (x^n)
  2. Lambda: استخدم Lambda لترتيب ArrayList من الأرقام
  3. تصفية: اكتب دالة عالية الدالة لتصفية المصفوفات بناءً على شرط

الدرس التالي

في الدرس التالي، سنتعلم النصوص — الأساسيات — التعامل مع النصوص في Java.

100%