Phase 2 · Functions & FunctionalModule 9~40 min read

Collection Operations

Transform data declaratively with map, filter, fold, groupBy, and Kotlin's rich collection API.

What you'll learn

This is where Kotlin's collections become a joy. Instead of writing loops, you describe what you want with a rich set of operations — map, filter, groupBy, and dozens more — chained into readable pipelines.

By the end you'll be able to:

  • Transform and filter collections with map and filter
  • Aggregate with reduce, fold, sum, and count
  • Group and partition data
  • Chain operations into clean pipelines

map & filter

These two are the workhorses. filter keeps only the elements matching a condition, and map transforms every element. Both take a lambda and return a new list:

MapFilter.kt
val nums = listOf(1, 2, 3, 4, 5, 6)

val evens = nums.filter { it % 2 == 0 }   // keep matching items
val squares = nums.map { it * it }        // transform each item

println(evens)     // [2, 4, 6]
println(squares)   // [1, 4, 9, 16, 25, 36]

reduce, fold & count

To collapse a collection into a single value, use an aggregate. sum(), count(), and maxOrNull() cover common cases; reduce and fold combine elements with your own logic (fold lets you supply a starting value):

Aggregate.kt
val nums = listOf(1, 2, 3, 4, 5)

println(nums.sum())                          // 15
println(nums.reduce { acc, n -> acc + n })   // 15 (combine all)
println(nums.fold(100) { acc, n -> acc + n })// 115 (start from 100)
println(nums.count { it > 2 })               // 3
println(nums.maxOrNull())                    // 5

Grouping & partitioning

groupBy classifies elements into a Map by a key you choose — perfect for reports. partition splits a collection in two based on a condition, returning a pair you can destructure:

Grouping.kt
val words = listOf("apple", "banana", "avocado", "cherry")

val byFirst = words.groupBy { it.first() }
println(byFirst)

// partition splits into (matching, non-matching)
val (long, short) = words.partition { it.length > 5 }
println(long)
println(short)
OperationWhat it does
map { }transform each element
filter { }keep elements matching a condition
groupBy { }classify into a Map by a key
sortedBy { }sort by a selector
find { } / any { } / all { }search / test elements
fold(init) { }combine into one value, from a start

Chaining into pipelines

Because each operation returns a new collection, you chain them — reading the logic top to bottom like a sentence. This one keeps the evens, squares them, and sums the result:

A collection pipeline
listOf(1..8)→.filter { even }→.map { square }→.sum()
Chaining.kt
val result = listOf(1, 2, 3, 4, 5, 6, 7, 8)
    .filter { it % 2 == 0 }   // [2, 4, 6, 8]
    .map { it * it }          // [4, 16, 36, 64]
    .sum()                    // 120

println(result)

Key idea

Read that pipeline like English: "take the numbers, keep the even ones, square them, and add them up." No index, no loop, no temporary variables — just intent. This is idiomatic Kotlin at its best.

Note

Each step builds an intermediate list. For very large collections, converting to a sequence (Module 21) makes the whole pipeline lazy — a big memory and speed win. For everyday lists, plain chaining is perfect.

Recap & quick check

Key takeaways

  • filter keeps matching elements; map transforms each — both return new lists.
  • sum/count/maxOrNull aggregate; reduce and fold combine with your own logic (fold takes a start value).
  • groupBy classifies into a Map by a key; partition splits into (matching, non-matching).
  • Chain operations into readable top-to-bottom pipelines.
  • For huge collections, use a sequence to make the pipeline lazy.

Quick check

1. What does filter do?

2. What does map do?

3. How does fold differ from reduce?

4. What does groupBy return?

5. Why chain collection operations?

Superb — you can process data declaratively now. Next up: Module 10 — Scope Functions.