تحويل التدفقات
طبّق map وfilter على البيانات المتدفقة
تحويل التدفقات درس مجاني في Scala for Backend Engineering & Functional Programming على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Scala for Backend Engineering & Functional Programming، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Scala for Backend Engineering & Functional Programming 4 دروس في المجموع.
بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.
Operators as Transformations
Akka Streams provides a rich set of operators on Source and Flow that mirror Scala's collection API but run asynchronously and respect backpressure.
Each operator returns a new blueprint, so transformations are composed declaratively before the stream ever runs.
map and filter
map applies a synchronous function to every element; filter drops elements that fail a predicate. These are the workhorses of element-wise transformation.
Both preserve ordering and propagate completion and failure downstream.
val flow =
Flow[Int]
.filter(_ % 2 == 0)
.map(n => n * n)mapConcat for One-to-Many
When one input should produce several outputs, use mapConcat. It takes a function returning an iterable and flattens the results into the stream.
Returning an empty collection effectively drops the element.
val explode: Flow[String, String, akka.NotUsed] =
Flow[String].mapConcat(line => line.split(",").toList)
val words = Source(List("a,b", "c,d,e"))
.via(explode)grouped and sliding
grouped(n) batches consecutive elements into a Seq of up to n items, useful for bulk database writes. sliding(n) emits overlapping windows.
Batching reduces per-element overhead in I/O-heavy pipelines.
val batches: Source[Seq[Int], akka.NotUsed] =
Source(1 to 1000).grouped(100)
val windows =
Source(1 to 10).sliding(3, step = 1)scan and fold
scan emits the running accumulator after each element, giving an evolving state stream. fold emits only the final accumulated value once upstream completes.
Use scan for live counters and fold for terminal aggregates.
val running =
Source(1 to 5).scan(0)(_ + _) // 0,1,3,6,10,15
val total =
Source(1 to 5).fold(0)(_ + _) // 15mapAsync for Async Work
mapAsync(parallelism) calls a function returning a Future and emits results in order, running up to parallelism futures concurrently.
Use it for asynchronous calls like database lookups or HTTP requests where ordering matters.
import scala.concurrent.Future
val enriched =
Flow[UserId]
.mapAsync(parallelism = 4)(id => lookup(id))
def lookup(id: UserId): Future[User] = ???mapAsyncUnordered
mapAsyncUnordered behaves like mapAsync but emits each result as soon as it completes, ignoring input order.
It can improve throughput when downstream does not care about ordering, since a slow future no longer blocks faster ones.
val fast =
Flow[UserId]
.mapAsyncUnordered(parallelism = 8)(id => lookup(id))Stateful Transformation with statefulMapConcat
For per-element transformations that need mutable local state, statefulMapConcat creates fresh state per materialization and returns an iterable of outputs.
It is the safe way to keep counters or buffers without sharing state across stream runs.
val withIndex: Flow[String, (Int, String), akka.NotUsed] =
Flow[String].statefulMapConcat { () =>
var i = 0
elem => { i += 1; List((i, elem)) }
}Time-Based Operators
Streams can transform on time as well as content. throttle caps the emission rate, groupedWithin batches by size or elapsed time, and takeWithin limits duration.
These are essential for rate-limiting external APIs.
import scala.concurrent.duration._
val limited =
Source(1 to 1000)
.throttle(10, 1.second)
.groupedWithin(100, 500.millis)Handling Errors in Transformations
A thrown exception inside an operator fails the whole stream by default. A supervision strategy can instead resume (drop the bad element) or restart the stage.
Attach the strategy with withAttributes on the Flow.
import akka.stream.{ActorAttributes, Supervision}
val safe =
Flow[String].map(_.toInt)
.withAttributes(
ActorAttributes.supervisionStrategy(_ => Supervision.Resume))Composing Flows
Small Flows compose into larger ones with via, producing a single reusable Flow. This keeps each transformation focused and independently testable.
The composed Flow has the input type of the first and the output type of the last.
val parse = Flow[String].map(_.toInt)
val square = Flow[Int].map(n => n * n)
val parseAndSquare: Flow[String, Int, akka.NotUsed] =
parse.via(square)Quick Check
Consider asynchronous transformations and their ordering guarantees.
Recap
You explored transformation operators: element-wise map/filter, one-to-many mapConcat, batching grouped, accumulation with scan and fold, and async work via mapAsync.
You also saw stateful transforms, time-based operators like throttle, supervision strategies for errors, and how Flows compose with via. Next: how backpressure keeps these stages safe.
الأسئلة الشائعة
هل درس «تحويل التدفقات» مجاني؟
نعم — نص درس «تحويل التدفقات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Scala for Backend Engineering & Functional Programming، انتقل إلى CoddyKit PRO. تتضمن دورة Scala for Backend Engineering & Functional Programming 4 دروس في المجموع.
ماذا ستتعلم في «تحويل التدفقات»؟
طبّق map وfilter على البيانات المتدفقة تتمرن على Scala for Backend Engineering & Functional Programming مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Scala for Backend Engineering & Functional Programming؟
لا تُشترط خبرة سابقة. Scala for Backend Engineering & Functional Programming على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «تحويل التدفقات»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Scala for Backend Engineering & Functional Programming هذا؟
نعم. كل درس في Scala for Backend Engineering & Functional Programming يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- Source وFlow وSink
- تحويل التدفقات
- التحكم في الضغط
- تشغيل خط أنابيب