Kotlin: شرح عمليات المجموعات في كوتلن
آخر تحديث: 2026-08-26
عمليات المجموعات في كوتلن تتيح لتشارلي استبدال الحلقات الأمرية بخطوط أنابيب تصريحية — سطر واحد يغني عن 15 سطراً من حلقة for، بنية أوضح.
1. ما ستتعلمه
- العوامل الأساسية:
map/filter/flatMap/groupBy/associate - المتتاليات الكسولة:
Sequenceيتجنب تخصيص المجموعات الوسيطة - التجميع:
fold/reduce/sumOf/count - الثابت مقابل المتغير:
ListمقابلMutableList - تشارلي في العمل: معالجة ملايين الطلبات بخط أنابيب وظيفي
2. قصة مهندس حقيقية
(1) نقطة الألم: OOM عند معالجة ملايين الطلبات
استخدم تشارلي List لمعالجة ملايين سجلات الطلبات. كل عملية وسيطة أنشأت مجموعة جديدة، تستهلك 3 جيجابايت من الذاكرة مما تسبب في OOM.
(2) حل التقييم الكسول مع Sequence
KOTLIN
// متحمس: ينشئ مجموعات وسيطة في كل خطوة
orders.map { enrich(it) } // المجموعة 1: مليون عنصر
.filter { it.total > 100 } // المجموعة 2: ~500 ألف عنصر
.toList() // المجموعة 3
// كسول: يعالج عنصر واحد عبر الخط بأكمله
orders.asSequence()
.map { enrich(it) }
.filter { it.total > 100 }
.toList() // مجموعة نهائية واحدة فقط
Sequence كخط تجميع: كل عنصر يمر عبر الخط بأكمله قبل أن يبدأ التالي — لا حاجة لمجموعات وسيطة.
3. العوامل الأساسية
(1) map — التحويل
KOTLIN
val orders = listOf(
Order("ORD-001", 299.99, "Alice"),
Order("ORD-002", 1_500.00, "Bob")
)
// تحويل كل عنصر
val ids = orders.map { it.id } // [ORD-001, ORD-002]
val summaries = orders.map { "${it.id}: \$${it.total} USD" }
// mapIndexed: مع الفهرس
orders.mapIndexed { i, order -> "[${i + 1}] ${order.id}" }
// mapNotNull: تحويل + تصفية القيم الفارغة
val emails = orders.mapNotNull { it.customerEmail }
(2) filter — التصفية
KOTLIN
// تصفية حسب الشرط
val highValue = orders.filter { it.total > 1_000 }
val pending = orders.filter { it.status == "PENDING" }
// filterNot: تصفية عكسية
val active = orders.filterNot { it.status == "CANCELLED" }
// filterIndexed: مع الفهرس
orders.filterIndexed { i, _ -> i % 2 == 0 } // الطلبات ذات الفهرس الزوجي
(3) flatMap — التحويل المسطّح
KOTLIN
data class Customer(val name: String, val orders: List<Order>)
val customers = listOf(
Customer("Alice", listOf(Order("ORD-001", 299.99), Order("ORD-002", 150.0))),
Customer("Bob", listOf(Order("ORD-003", 1_500.00)))
)
// تحويل + تسطيح في خطوة واحدة
val allOrders = customers.flatMap { it.orders }
// [Order(ORD-001, 299.99), Order(ORD-002, 150.0), Order(ORD-003, 1500.0)]
(4) groupBy — التجميع
KOTLIN
// تجميع حسب المفتاح
val byCustomer: Map<String, List<Order>> = orders.groupBy { it.customer }
// تجميع مع تحويل القيمة
val totalsByCustomer = orders.groupBy(
keySelector = { it.customer },
valueTransform = { it.total }
)
// {Alice=[299.99], Bob=[1500.0]}
(5) associate — الربط بـ Map
KOTLIN
// إنشاء Map من قائمة
val orderMap = orders.associate { it.id to it }
// {ORD-001=Order(...), ORD-002=Order(...)}
// associateBy: منتقي المفتاح
val byId = orders.associateBy { it.id }
// associateBy مع تحويل القيمة
val totalsById = orders.associateBy(
keySelector = { it.id },
valueTransform = { it.total }
)
(6) مرجع سريع للعوامل
| العامل | الوظيفة | الإدخال → الإخراج | تشبيه SQL |
|---|---|---|---|
map |
تحويل | List<A> → List<B> |
SELECT |
filter |
تصفية | List<T> → List<T> |
WHERE |
flatMap |
تحويل مسطّح | List<A> → List<B> |
JOIN + SELECT |
groupBy |
تجميع | List<T> → Map<K, List<T>> |
GROUP BY |
associate |
ربط | List<T> → Map<K, V> |
- |
distinct |
إزالة التكرار | List<T> → List<T> |
DISTINCT |
sortedBy |
فرز | List<T> → List<T> |
ORDER BY |
4. خط أنابيب عمليات المجموعات
flowchart LR
A[طلبات<br/>مليون سجل] --> B[filter<br/>total > 1000]
B --> C[map<br/>استخراج العميل]
C --> D[distinct<br/>عملاء فريدون]
D --> E[groupBy<br/>حسب المنطقة]
E --> F[النتيجة<br/>Map من العملاء]
5. التقييم الكسول مع Sequence
(1) متحمس مقابل كسول
KOTLIN
// متحمس (List): كل خطوة تنشئ مجموعة جديدة
val result = orders
.map { println("map: ${it.id}"); it.copy(total = it.total * 0.9) }
.filter { println("filter: ${it.id}"); it.total > 100 }
.take(2)
.toList()
// كسول (Sequence): يعالج عنصر واحد في كل مرة
val result2 = orders.asSequence()
.map { println("seq-map: ${it.id}"); it.copy(total = it.total * 0.9) }
.filter { println("seq-filter: ${it.id}"); it.total > 100 }
.take(2)
.toList()
// Sequence يعالج العناصر فقط حتى يُلبى شرط take(2)
(2) متى تستخدم Sequence
| السيناريو | استخدم List | استخدم Sequence |
|---|---|---|
| حجم البيانات | < 10,000 | > 10,000 |
| خطوات العملية | 1-2 خطوة | 3+ خطوات |
| حجم النتيجة الوسيطة | قريب من حجم المصدر | مُقلص بشكل كبير |
| حاجة لاجتيازات متعددة | نعم | لا |
(3) أداء List مقابل Sequence
| البُعد | List (متحمس) | Sequence (كسول) |
|---|---|---|
| المجموعات الوسيطة | تُنشأ في كل خطوة | لا تُنشأ |
| الذاكرة | O(n × خطوات) | O(1) |
| عمليات الدائرة القصيرة | غير محسّنة | محسّنة (مثلاً take يعالج N فقط) |
| أول نتيجة | تنتظر الخط الكامل | متاحة فوراً |
6. عمليات التجميع
(1) fold / reduce
KOTLIN
// fold: مع قيمة ابتدائية
val totalRevenue = orders.fold(0.0) { acc, order -> acc + order.total }
// reduce: العنصر الأول كقيمة ابتدائية
val maxOrder = orders.reduce { max, order ->
if (order.total > max.total) order else max
}
// foldRight: من النهاية إلى البداية
val reversed = orders.foldRight(emptyList<Order>()) { order, acc -> acc + order }
(2) التجميع المريح
KOTLIN
val total = orders.sumOf { it.total }
val avg = orders.map { it.total }.average()
val max = orders.maxByOrNull { it.total }
val min = orders.minByOrNull { it.total }
val count = orders.count { it.total > 1_000 }
// الفرز
val sorted = orders.sortedByDescending { it.total }
val top3 = orders.sortedByDescending { it.total }.take(3)
(3) fold مقابل reduce
| البُعد | fold |
reduce |
|---|---|---|
| القيمة الابتدائية | يجب تحديدها | العنصر الأول ضمنياً |
| المجموعة الفارغة | آمن (يرجع القيمة الابتدائية) | يطرح استثناء |
| نوع الإرجاع | يمكن أن يختلف عن نوع العنصر | نفس نوع العنصر |
| التوصية | ⭐⭐⭐ | ⭐⭐ |
7. المجموعات الثابتة مقابل المتغيرة
(1) واجهات القراءة فقط والمتغيرة
KOTLIN
// للقراءة فقط (واجهة ثابتة)
val list: List<Order> = listOf(Order("ORD-001", 299.99, "Alice"))
// متغيرة
val mutableList: MutableList<Order> = mutableListOf()
mutableList.add(Order("ORD-002", 1_500.00, "Bob"))
// عرض القراءة فقط لقائمة متغيرة
val readOnly: List<Order> = mutableList // صحيح: MutableList يرث من List
// readOnly.add(...) // خطأ: List لا يمتلك تابع add
mutableList.add(Order("ORD-003", 45.50, "Charlie")) // يغير عرض readOnly!
(2) النسخة الدفاعية
KOTLIN
class OrderProcessor(private val _orders: MutableList<Order>) {
// نسخة دفاعية: كشف عرض ثابت
val orders: List<Order> get() = _orders.toList()
// أو استخدام عرض ثابت (بدون نسخ، لكن يمكن إرجاعه بالتحويل)
val ordersView: List<Order> get() = _orders.toList()
}
(3) مقارنة أنواع المجموعات
| النوع | واجهة القراءة فقط | الواجهة المتغيرة | دوال الإنشاء |
|---|---|---|---|
| List | List |
MutableList |
listOf / mutableListOf |
| Set | Set |
MutableSet |
setOf / mutableSetOf |
| Map | Map |
MutableMap |
mapOf / mutableMapOf |
8. مثال كامل: خط معالجة ملايين الطلبات
KOTLIN
// ============================================
// OrderProcessor - خط عمليات المجموعات
// الميزة: معالجة الطلبات بعوامل وظيفية
// ============================================
data class Order(val id: String, val total: Double, val status: String, val customer: String, val region: String)
fun main() {
// محاكاة بيانات الطلبات
val orders = listOf(
Order("ORD-001", 299.99, "CONFIRMED", "Alice", "US"),
Order("ORD-002", 15_000.00, "CONFIRMED", "Bob", "EU"),
Order("ORD-003", 2_500.00, "PENDING", "Charlie", "US"),
Order("ORD-004", 45.50, "CANCELLED", "Alice", "ASIA"),
Order("ORD-005", 8_900.00, "CONFIRMED", "Bob", "EU"),
Order("ORD-006", 1_200.00, "SHIPPED", "Charlie", "US"),
Order("ORD-007", 350.00, "CONFIRMED", "Alice", "ASIA"),
Order("ORD-008", 22_000.00, "PENDING", "Bob", "EU"),
Order("ORD-009", 750.00, "CONFIRMED", "Charlie", "US"),
Order("ORD-010", 4_500.00, "SHIPPED", "Alice", "US")
)
// خط أنابيب 1: الطلبات المؤكدة عالية القيمة
println("=== High-Value Confirmed Orders ===")
orders.filter { it.status == "CONFIRMED" && it.total > 1_000 }
.sortedByDescending { it.total }
.forEach { println(" ${it.id}: \$${it.total} USD (${it.customer})") }
// خط أنابيب 2: الإيرادات حسب المنطقة
println("\n=== Revenue by Region ===")
orders.filter { it.status != "CANCELLED" }
.groupBy { it.region }
.mapValues { (_, list) -> list.sumOf { it.total } }
.forEach { (region, revenue) -> println(" $region: \$$revenue USD") }
// خط أنابيب 3: أفضل العملاء حسب عدد الطلبات والإيرادات
println("\n=== Customer Summary ===")
orders.filter { it.status != "CANCELLED" }
.groupBy { it.customer }
.map { (customer, list) ->
val count = list.size
val total = list.sumOf { it.total }
val avg = list.map { it.total }.average()
"$customer: $count orders, \$${total} USD total, \$${"%.2f".format(avg)} avg"
}
.forEach { println(" $it") }
// خط أنابيب 4: استخدام Sequence لمعالجة فعالة
println("\n=== Top 3 Orders (Sequence) ===")
orders.asSequence()
.filter { it.status != "CANCELLED" }
.sortedByDescending { it.total }
.take(3)
.forEach { println(" ${it.id}: \$${it.total} USD") }
// تجميع: fold لبناء سلسلة ملخصة
val summary = orders
.filter { it.status != "CANCELLED" }
.fold("Order Summary: ") { acc, order -> "$acc\n ${order.id} (\$${order.total} USD)" }
println("\n${summary}")
println("Total orders: ${orders.size}, Active: ${orders.count { it.status != "CANCELLED" }}")
}
المخرجات:
TEXT
📖 للعرض فقط
=== High-Value Confirmed Orders ===
ORD-005: $8900.0 USD (Bob)
ORD-002: $15000.0 USD (Bob)
=== Revenue by Region ===
US: $7599.99 USD
EU: $46400.0 USD
ASIA: $350.0 USD
=== Customer Summary ===
Alice: 2 orders, $3649.99 USD total, $1824.995 avg
Bob: 3 orders, $46400.0 USD total, $15466.666666666666 avg
Charlie: 3 orders, $4450.0 USD total, $1483.3333333333333 avg
=== Top 3 Orders (Sequence) ===
ORD-008: $22000.0 USD (Bob)
ORD-002: $15000.0 USD (Bob)
ORD-005: $8900.0 USD (Bob)
Order Summary:
ORD-001 ($299.99 USD)
ORD-002 ($15000.0 USD)
ORD-003 ($2500.0 USD)
ORD-005 ($8900.0 USD)
ORD-006 ($1200.0 USD)
ORD-007 ($350.0 USD)
ORD-008 ($22000.0 USD)
ORD-009 ($750.0 USD)
ORD-010 ($4500.0 USD)
Total orders: 10, Active: 9
9. أمثلة عملية سريعة
▶ مثال: List وعملياتها الأساسية
KOTLIN
// إنشاء قوائم بأنواع مختلفة
val numbers = listOf(1, 2, 3, 4, 5)
val names = mutableListOf("Alice", "Bob")
val mixed = listOf(1, "two", 3.0) // List<Any>
// الوصول والتعديل
println("First: ${numbers.first()}")
println("Last: ${numbers.last()}")
println("Size: ${numbers.size}")
println("Contains 3: ${numbers.contains(3)}")
println("Index of 3: ${numbers.indexOf(3)}")
// إضافة وحذف
names.add("Charlie")
names.remove("Bob")
println("Names: $names")
// عكس، فرز
val reversed = numbers.reversed()
val sorted = listOf(3, 1, 4, 1, 5, 9, 2, 6).sorted()
println("Reversed: $reversed")
println("Sorted: $sorted")
**المخرجات:
TEXT
📖 للعرض فقط
First: 1
Last: 5
Size: 5
Contains 3: true
Index of 3: 2
Names: [Alice, Charlie]
Reversed: [5, 4, 3, 2, 1]
Sorted: [1, 1, 2, 3, 4, 5, 6, 9]
▶ مثال: map و filter و reduce
KOTLIN
val orders = listOf(
Order("O1", 100.0, "PENDING"),
Order("O2", 250.0, "CONFIRMED"),
Order("O3", 50.0, "CANCELLED"),
Order("O4", 800.0, "CONFIRMED"),
Order("O5", 150.0, "PENDING")
)
// map - تحويل
val totals = orders.map { it.total }
println("Totals: $totals")
// filter - تصفية
val confirmedOrders = orders.filter { it.status == "CONFIRMED" }
println("Confirmed count: ${confirmedOrders.size}")
// combine map + filter
val confirmedTotals = orders
.filter { it.status == "CONFIRMED" }
.map { it.total }
println("Confirmed totals: $confirmedTotals")
// reduce - تجميع
val totalRevenue = orders
.filter { it.status != "CANCELLED" }
.map { it.total }
.reduce { acc, total -> acc + total }
println("Total revenue: \$$totalRevenue USD")
// fold - مع قيمة ابتدائية
val summary = orders.fold("Orders:") { acc, order ->
"$acc ${order.id}"
}
println(summary)
// any, all, none
println("Any confirmed? ${orders.any { it.status == "CONFIRMED" }}")
println("All confirmed? ${orders.all { it.status == "CONFIRMED" }}")
println("None cancelled? ${orders.none { it.status == "CANCELLED" }}")
**المخرجات:
TEXT
📖 للعرض فقط
Totals: [100.0, 250.0, 50.0, 800.0, 150.0]
Confirmed count: 2
Confirmed totals: [250.0, 800.0]
Total revenue: $1300.0
Orders: O1 O2 O3 O4 O5
Any confirmed? true
All confirmed? false
None cancelled? false
▶ مثال: Set و Map
KOTLIN
// Set - عناصر فريدة
val uniqueStatuses = setOf("PENDING", "CONFIRMED", "CANCELLED", "PENDING")
println("Set: $uniqueStatuses")
println("Size: ${uniqueStatuses.size}") // 3 (لا تكرار)
// Map - أزواج مفتاح-قيمة
val priceMap = mapOf(
"Laptop" to 1299.99,
"Mouse" to 29.99,
"Keyboard" to 79.99
)
println("Map: $priceMap")
println("Laptop price: \$${priceMap["Laptop"]} USD")
// إضافة وتعديل
val mutablePrices = priceMap.toMutableMap()
mutablePrices["Monitor"] = 499.99
mutablePrices["Mouse"] = 24.99 // تعديل
println("Updated: $mutablePrices")
// التحقق من وجود مفتاح
println("Has Laptop? ${priceMap.containsKey("Laptop")}")
println("Has value 79.99? ${priceMap.containsValue(79.99)}")
// تحويل Map.entries
val sortedByValue = priceMap.entries.sortedBy { it.value }
println("Sorted by value: $sortedByValue")
**المخرجات:
TEXT
📖 للعرض فقط
Set: [PENDING, CONFIRMED, CANCELLED]
Size: 3
Map: {Laptop=1299.99, Mouse=29.99, Keyboard=79.99}
Laptop price: $1299.99 USD
Updated: {Laptop=1299.99, Mouse=24.99, Keyboard=79.99, Monitor=499.99}
Has Laptop? true
Has value 79.99? true
Sorted by value: [Mouse=24.99, Keyboard=79.99, Monitor=499.99, Laptop=1299.99]
▶ مثال: groupBy و partition
KOTLIN
val items = listOf(
"apple" to 1.20,
"banana" to 0.50,
"apple" to 1.30,
"kiwi" to 2.00,
"banana" to 0.45,
"apple" to 1.25
)
// groupBy - تجميع حسب مفتاح
val byName = items.groupBy { it.first }
println("Apples: ${byName["apple"]?.size}")
println("Bananas: ${byName["banana"]?.size}")
// تجميع مع عملية
val sumByName = items.groupBy(
{ it.first },
{ it.second }
).mapValues { (_, prices) -> prices.sum() }
println("Total prices: $sumByName")
// partition - تقسيم حسب شرط
val (cheap, expensive) = items.partition { it.second < 1.0 }
println("Cheap: ${cheap.size}, Expensive: ${expensive.size}")
// associateBy - قائمة إلى Map
val byKey = items.associateBy { it.first }
println("First banana: ${byKey["banana"]}")
**المخرجات:
TEXT
📖 للعرض فقط
Apples: 3
Bananas: 2
Total prices: {apple=3.75, banana=0.95, kiwi=2.0}
Cheap: 2, Expensive: 4
First banana: (banana, 0.45)
▶ مثال: Sequence للأداء
KOTLIN
// مع List - تنفيذ متزامن (immediate)
val listResult = listOf(1, 2, 3, 4, 5)
.map { it * 2 } // يطبق على كل العناصر فوراً
.filter { it > 4 } // يطبق على كل العناصر
.take(2) // يأخذ أول 2
.toList()
println("List: $listResult")
// مع Sequence - تنفيذ كسول
val seqResult = sequenceOf(1, 2, 3, 4, 5)
.map { it * 2 }
.filter { it > 4 }
.take(2)
.toList()
println("Sequence: $seqResult")
// مثال عملي: معالجة مليون عنصر
val largeList = (1..1_000_000).toList()
// List: O(n) في كل خطوة
val listTime = measureTime {
largeList
.map { it * 2 }
.filter { it > 1_000_000 }
.take(10)
.toList()
}
println("List time: ${listTime}ms")
// Sequence: يوقف عند take(10)
val seqTime = measureTime {
largeList.asSequence()
.map { it * 2 }
.filter { it > 1_000_000 }
.take(10)
.toList()
}
println("Sequence time: ${seqTime}ms")
**المخرجات:
TEXT
📖 للعرض فقط
List: [6, 8]
Sequence: [6, 8]
List time: Xms
Sequence time: Yms
▶ مثال: groupBy و aggregate
KOTLIN
data class Sale(val product: String, val amount: Double, val month: String)
val sales = listOf(
Sale("Laptop", 1299.99, "Jan"),
Sale("Mouse", 29.99, "Jan"),
Sale("Laptop", 1499.99, "Feb"),
Sale("Mouse", 24.99, "Feb"),
Sale("Keyboard", 79.99, "Feb"),
Sale("Laptop", 1199.99, "Mar")
)
// تجميع حسب المنتج
val byProduct = sales.groupBy(
{ it.product },
{ it.amount }
).mapValues { (_, amounts) -> amounts.sum() }
println("Revenue by product: $byProduct")
// تجميع متعدد المستويات
val byProductMonth = sales.groupBy { it.product }
.mapValues { (_, sales) ->
sales.groupBy(
{ it.month },
{ it.amount }
).mapValues { (_, amounts) -> amounts.sum() }
}
println("Revenue by product & month: $byProductMonth")
// count مع شرط
val laptopSales = sales.count { it.product == "Laptop" }
println("Laptop sales count: $laptopSales")
// sumOf مع selector
val totalJan = sales.sumOf { if (it.month == "Jan") it.amount else 0.0 }
println("January total: \$$totalJan USD")
**المخرجات:
TEXT
📖 للعرض فقط
Revenue by product: {Laptop=3999.97, Mouse=54.98, Keyboard=79.99}
Revenue by product & month: {Laptop={Jan=1299.99, Feb=1499.99, Mar=1199.99}, Mouse={Jan=29.99, Feb=24.99}, Keyboard={Feb=79.99}}
Laptop sales count: 3
January total: $1329.98 USD
▶ مثال: zip و flatten
KOTLIN
val names = listOf("Alice", "Bob", "Charlie")
val ages = listOf(30, 25, 35)
val cities = listOf("NYC", "LA", "Chicago")
// zip - دمج قائمتين
val nameAgePairs = names.zip(ages)
println("Pairs: $nameAgePairs")
// zip مع تحويل
val profiles = names.zip(ages) { name, age -> "$name ($age)" }
println("Profiles: $profiles")
// zip ثلاث قوائم
val triples = names.zip(ages).zip(cities) { (n, a), c -> Triple(n, a, c) }
println("Triples: $triples")
// flatten قائمة من القوائم
val nested = listOf(listOf(1, 2), listOf(3, 4), listOf(5, 6))
val flat = nested.flatten()
println("Flattened: $flat")
// flatMap
val words = listOf("Hello", "World")
val chars = words.flatMap { it.toList() }
println("Chars: $chars")
**المخرجات:
TEXT
📖 للعرض فقط
Pairs: [(Alice, 30), (Bob, 25), (Charlie, 35)]
Profiles: [Alice (30), Bob (25), Charlie (35)]
Triples: [(Alice, 30, NYC), (Bob, 25, LA), (Charlie, 35, Chicago)]
Flattened: [1, 2, 3, 4, 5, 6]
Chars: [H, e, l, l, o, W, o, r, l, d]
❓ أسئلة شائعة
س ما الفرق بين عمليات مجموعات كوتلن و Java Stream؟
ج عمليات مجموعات كوتلن أكثر إيجازاً (كلمة
it، لامبدا خلفية)، لا حاجة لتحويلات stream()/collect()، و Sequence مشابه لـ Stream لكن أخف.س متى يجب أن أستخدم Sequence؟
ج استخدم Sequence عندما تكون البيانات كبيرة (>10,000)، أو خطوات العملية كثيرة (3+)، أو تحتاج عمليات دائرة قصيرة (
take/first). للبيانات الصغيرة، List أبسط.س هل
toList() تنسخ البيانات؟ج نعم.
toList() تنشئ قائمة جديدة — إنها نسخة دفاعية. إذا احتجت فقط عرض قراءة فقط بدون نسخ، استخدم مرجع واجهة List.س fold أو reduce — أيهما أختار؟
ج فضّل
fold لأنه يسمح بتحديد قيمة ابتدائية وآمن للمجموعات الفارغة. reduce يطرح استثناء على المجموعات الفارغة.س هل List في كوتلن ثابتة حقاً؟
ج لا.
List في كوتلن واجهة للقراءة فقط (لا يمكن تعديلها من خلالها)، لكن التطبيق الأساسي قد يكون متغيراً. الثبات الحقيقي يتطلب إنشاء نسخة بـ toList().س هل هناك فرق بين
flatMap و map + flatten؟ج متكافئان وظيفياً؛
flatMap أكثر كفاءة (يتم في خطوة واحدة). إنه الاختصار المدمج لـ map + flatten.📖 ملخص
- العوامل الأساسية:
map(تحويل)،filter(تصفية)،flatMap(تحويل مسطّح)،groupBy(تجميع)،associate(ربط بـ Map) - التقييم الكسول مع Sequence يتجنب تخصيص المجموعات الوسيطة — مفضل لمجموعات البيانات الكبيرة
fold(له قيمة ابتدائية، آمن) مفضل علىreduce(غير آمن على المجموعات الفارغة)Listواجهة للقراءة فقط،MutableListمتغيرة — فضّل القراءة فقط- النسخة الدفاعية بـ
toList()تحمي الحالة المتغيرة الداخلية - خطوط أنابيب عمليات المجموعات تجعل كود معالجة البيانات تصريحياً ومقروءاً وقابلاً للتركيب
📝 تمارين
- مبتدئ (⭐): استخدم
filterوmapلاستخراج معرفات الطلبات ذات المبالغ > 1000 دولار من قائمة طلبات. تلميح:orders.filter { }.map { } - متوسط (⭐⭐): استخدم
groupBy+mapValuesلحساب إجمالي إنفاق كل عميل، مرتباً تنازلياً حسب المبلغ. تلميح:groupBy { it.customer }.mapValues { } - متقدم (⭐⭐⭐): استخدم
Sequenceلتنفيذ خط معالجة كسول لملايين الطلبات: filter → map → take(100)، واطبع عدد العناصر المعالجة فعلياً. تلميح: استخدم عداداً فيonEach