توليد التدفقات البدائية
iterate وgenerate
توليد التدفقات البدائية درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.
تحتاج التدفقات اللانهائية إلى حدود
تنشئ iterate وgenerate تدفقات قد تكون لانهائية. ويجب إضافة limit أو مسند لجعلها منتهية.
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
IntStream.iterate(1, n -> n + 1)
.limit(5)
.forEach(System.out::println);
}
}التكرار باستخدام قيمة البدء
تبدأ iterate(seed, next) من قيمة البدء، ثم تطبّق الدالة بصورة متكررة على القيمة السابقة.
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
IntStream.iterate(2, n -> n * 2)
.limit(5)
.forEach(System.out::println);
}
}التكرار باستخدام Predicate
تتوقف iterate(seed, hasNext, next) ذات المعاملات الثلاثة تلقائيًا عندما تصبح دالة الشرط خاطئة، مثل حلقة for الوظيفية.
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
IntStream.iterate(1, n -> n <= 100, n -> n * 3)
.forEach(System.out::println);
}
}التوليد باستخدام Supplier
تستقبل generate كائنًا من نوع IntSupplier يُنتج كل عنصر بشكل مستقل، دون اعتماد على القيمة السابقة.
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
IntStream.generate(() -> 7)
.limit(3)
.forEach(System.out::println);
}
}توليد أرقام عشوائية
يمكن لمزوّد generate استدعاء مصدر عشوائي. في هذه الحالة، يمثل كل عنصر رمية نرد مستقلة.
import java.util.Random;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
Random rnd = new Random(42);
IntStream.generate(() -> rnd.nextInt(6) + 1)
.limit(5)
.forEach(System.out::println);
}
}iterate مقابل generate
الفرق الأساسي:
iterate: تُشتق كل قيمة من القيمة السابقة (تسلسلات).generate: يُنتج كل عنصر بشكل مستقل (ثوابت وأرقام عشوائية).
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
int sum = IntStream.iterate(1, n -> n + 1).limit(10).sum();
System.out.println(sum);
}
}تجميع التدفقات المولَّدة
بعد تحديد عدد عناصرها، تدعم التدفقات المولَّدة جميع عمليات التجميع المعتادة.
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
long count = IntStream.iterate(0, n -> n + 2)
.limit(50)
.filter(n -> n % 3 == 0)
.count();
System.out.println(count);
}
}متتالية فيبوناتشي باستخدام iterate على تدفق كائنات
بالنسبة إلى التسلسلات ذات الحالة مثل فيبوناتشي، استخدم Stream.iterate على مصفوفة تحتوي على زوج من القيم، ثم حوّل القيم مجددًا إلى int.
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.iterate(new int[]{0, 1}, p -> new int[]{p[1], p[0] + p[1]})
.limit(8)
.mapToInt(p -> p[0])
.forEach(System.out::println);
}
}بناء مصفوفة من مولِّد
اجمع بين مولِّد وtoArray لبناء مصفوفة أولية بطريقة إجرائية.
import java.util.Arrays;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
int[] squares = IntStream.iterate(1, n -> n + 1)
.limit(5)
.map(n -> n * n)
.toArray();
System.out.println(Arrays.toString(squares));
}
}التقييم الكسول يوفّر العمل
تتسم التدفقات بالتقييم الكسول: عند استخدام limit، لا تُولَّد إلا العناصر المطلوبة، حتى عند استخدام مصدر لا نهائي.
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
int first = IntStream.iterate(10, n -> n + 10)
.filter(n -> n > 25)
.findFirst()
.getAsInt();
System.out.println(first);
}
}فضّل الصيغة المعتمدة على Predicate
غالبًا ما يكون iterate المعتمد على دالة شرط أوضح من iterate(...).limit(...)، لأن شرط التوقف يكون موجودًا مع منطق التوليد.
import java.util.stream.LongStream;
public class Main {
public static void main(String[] args) {
long product = LongStream.iterate(1, n -> n <= 5, n -> n + 1)
.reduce(1, (a, b) -> a * b);
System.out.println(product);
}
}تحقق سريع
ماذا يحدث عند استدعاء generate من دون limit، ثم استخدام عملية نهائية مثل forEach؟
مراجعة
لقد ولّدت تدفقات من الأنواع الأولية:
iterateيشتق كل قيمة من القيمة السابقة.generateيُنتج القيم بشكل مستقل من مزوّد.- كلاهما لا نهائي؛ حددهما باستخدام
limitأو الصيغة المعتمدة على دالة الشرط منiterate. - يعني التقييم الكسول أنه لا يتم حساب إلا العناصر المطلوبة.
الأسئلة الشائعة
هل درس «توليد التدفقات البدائية» مجاني؟
نعم — نص درس «توليد التدفقات البدائية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.
ماذا ستتعلم في «توليد التدفقات البدائية»؟
iterate وgenerate تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟
لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «توليد التدفقات البدائية»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟
نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- IntStream وLongStream
- عمليات النطاق والتجميع
- التحويل من تدفقات الكائنات وإليها
- توليد التدفقات البدائية