0Pricing
Java Academy · درس

‏flatMap للمجموعات المتداخلة

بسّط القوائم المتداخلة وسلاسل Optional وبُنى أسطر الملفات باستخدام flatMap

‏flatMap للمجموعات المتداخلة درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.

مشكلة المجموعات المتداخلة

عندما يحوّل كل عنصر في stream إلى مجموعة أخرى، ينتج map قيمة من النوع Stream<List<T>>. أما flatMap فيدمج التدفقات الداخلية في تدفق واحد مسطح من النوع Stream<T>.

List<List<Integer>> nested = List.of(List.of(1,2), List.of(3,4), List.of(5));
// With map:
Stream<List<Integer>> s = nested.stream().map(l -> l); // Stream<List<Integer>>
// With flatMap:
Stream<Integer> flat = nested.stream().flatMap(List::stream); // Stream<Integer>
flat.forEach(System.out::println); // 1 2 3 4 5

flatMap مقابل map

تطبّق map(f) الدالة f على كل عنصر وتغلّف النتيجة. أما flatMap(f) فتطبّق f التي تُرجع تدفقًا، ثم توحّد جميع تلك التدفقات في تدفق واحد.

// map: List<String> -> Stream<Stream<Character>>
Stream<Stream<Character>> nested = List.of("hi","bye").stream()
    .map(s -> s.chars().mapToObj(c -> (char)c));
// flatMap: List<String> -> Stream<Character>
Stream<Character> flat = List.of("hi","bye").stream()
    .flatMap(s -> s.chars().mapToObj(c -> (char)c));

تسطيح الطلبات والعناصر

استخدام شائع: يحتوي كل طلب على قائمة من العناصر. احصل على تدفق مسطح يضم جميع العناصر في جميع الطلبات.

List<String> allItems = orders.stream()
    .flatMap(order -> order.getItems().stream())
    .collect(Collectors.toList());
System.out.println(allItems);

flatMap مع Optional

استخدم stream() مع Optional (في Java 9 والإصدارات الأحدث) لتحويله إلى تدفق يضم صفرًا أو عنصرًا واحدًا. ثم يطوي flatMap القيمة Stream<Optional<T>> إلى Stream<T>.

List<Optional<String>> maybes = List.of(Optional.of("a"), Optional.empty(), Optional.of("c"));
List<String> values = maybes.stream()
    .flatMap(Optional::stream)  // Java 9+
    .collect(Collectors.toList());
System.out.println(values); // [a, c]

قراءة جميع الأسطر من ملفات متعددة

يسهّل flatMap دمج جميع الأسطر من قائمة ملفات في تدفق واحد دون استخدام حلقات متداخلة.

List<Path> files = List.of(Path.of("a.txt"), Path.of("b.txt"));
List<String> allLines = files.stream()
    .flatMap(p -> {
        try { return Files.lines(p); }
        catch (IOException e) { return Stream.empty(); }
    })
    .collect(Collectors.toList());

تقسيم السلاسل إلى كلمات

قسّم كل جملة إلى كلمات، ثم اطوِ جميع الكلمات في تدفق واحد لحساب تكرار الكلمات.

List<String> sentences = List.of("hello world", "java streams rock");
Map<String, Long> freq = sentences.stream()
    .flatMap(s -> Arrays.stream(s.split("\\s+")))
    .collect(Collectors.groupingBy(w -> w, Collectors.counting()));
System.out.println(freq);

flatMap مع Map.entrySet

اطوِ خريطةً تربط الفئات بقوائم العناصر في تدفق يضم جميع العناصر.

Map<String, List<String>> catalog = Map.of(
    "fruit", List.of("apple","banana"),
    "veg",   List.of("carrot","pea"));
List<String> all = catalog.values().stream()
    .flatMap(List::stream)
    .sorted()
    .collect(Collectors.toList());
System.out.println(all); // [apple, banana, carrot, pea]

تجنب NullPointerException في flatMap

إذا كان من الممكن أن تُرجع الدالة null بدلًا من تدفق، فاستخدم فحصًا للقيمة الفارغة أو أرجع Stream.empty() لتجنب NullPointerException.

departments.stream()
    .flatMap(dept -> dept.getEmployees() == null
        ? Stream.empty()
        : dept.getEmployees().stream())
    .forEach(System.out::println);

حساب الكلمات الفريدة باستخدام flatMap

اجمع بين flatMap وdistinct وcount لمعالجة البيانات بإيجاز.

long distinctWords = sentences.stream()
    .flatMap(s -> Arrays.stream(s.toLowerCase().split("[^a-z]+")))
    .filter(w -> !w.isEmpty())
    .distinct()
    .count();
System.out.println("Distinct: " + distinctWords);

flatMapToInt للتدفقات البدائية

استخدم flatMapToInt وflatMapToLong وflatMapToDouble لتجنب التغليف عند التسطيح إلى تدفقات من الأنواع البدائية.

int totalQuantity = orders.stream()
    .flatMapToInt(order -> order.getItems().stream().mapToInt(Item::getQuantity))
    .sum();
System.out.println("Total qty: " + totalQuantity);

ملاحظة حول الأداء

تضيف كل عملية flatMap طبقة تدفق. وعند التعامل مع مجموعات بيانات ضخمة تضم العديد من المجموعات الداخلية الصغيرة، فكّر في استخدام أساليب تكرارية أو Spliterator لتقليل تكلفة إنشاء الكائنات.

تحقق سريع

ما الذي يفعله flatMap بشكل مختلف عن map؟

مراجعة

يحوّل flatMap كل عنصر إلى تدفق، ثم يدمج جميع التدفقات في تدفق واحد. استخدمه لتسطيح المجموعات المتداخلة، وتسلسل قيم Optional، وتقسيم السلاسل، وقراءة ملفات متعددة. واستخدم flatMapToInt لتجنب التغليف.

الأسئلة الشائعة

هل درس «‏flatMap للمجموعات المتداخلة» مجاني؟

نعم — نص درس «‏flatMap للمجموعات المتداخلة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.

ماذا ستتعلم في «‏flatMap للمجموعات المتداخلة»؟

بسّط القوائم المتداخلة وسلاسل Optional وبُنى أسطر الملفات باستخدام flatMap تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟

لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «‏flatMap للمجموعات المتداخلة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟

نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. ‏flatMap للمجموعات المتداخلة
  2. التدفقات المتوازية: الأداء والمشكلات
  3. ‏Spliterator: التقسيم لتحقيق التوازي
  4. التدفقات اللانهائية باستخدام iterate وgenerate
← العودة إلى Java Academy