Collections & Functional Operations
The three collection types
- List — an ordered series of items (can repeat).
- Set — a collection of unique items (no duplicates).
- Map — key → value pairs (like a dictionary).
Each comes in a read-only and a mutable form. Prefer read-only unless you need to change the contents.
val list = listOf(1, 2, 3) // read-only
val mutable = mutableListOf(1, 2) // can add/remove
mutable.add(3)
val set = setOf(1, 1, 2, 3) // -> [1, 2, 3]
val map = mapOf("a" to 1, "b" to 2)
println(map["a"]) // 1
Why functional operations beat loops
Instead of writing for loops with temporary variables, Kotlin gives you readable operations that describe what you want. They’re shorter and less error-prone.
val nums = listOf(1, 2, 3, 4, 5, 6)
nums.filter { it % 2 == 0 } // keep evens -> [2, 4, 6]
nums.map { it * it } // transform -> [1, 4, 9, 16, 25, 36]
nums.first { it > 3 } // first match -> 4
nums.find { it > 10 } // or null -> null
nums.any { it > 5 } // is one true -> true
nums.all { it > 0 } // all true -> true
nums.count { it % 2 == 0 } // how many -> 3
nums.sumOf { it } // total -> 21
nums.maxOrNull() // 6
nums.sorted() // [1,2,3,4,5,6]
nums.groupBy { it % 2 } // {1=[1,3,5], 0=[2,4,6]}
nums.associateWith { it * it } // {1=1, 2=4, ...}
Chaining operations
The real power comes from chaining — each step feeds the next, reading top to bottom like a sentence.
data class User(val name: String, val age: Int, val city: String)
val users = listOf(
User("Anand", 28, "Delhi"),
User("Priya", 34, "Mumbai"),
User("Ravi", 22, "Delhi")
)
val delhiNamesSorted = users
.filter { it.city == "Delhi" } // only Delhi
.sortedBy { it.age } // youngest first
.map { it.name } // just the names
// -> [Ravi, Anand]
Maps in practice
val counts = mutableMapOf<String, Int>()
for (word in listOf("a", "b", "a")) {
counts[word] = (counts[word] ?: 0) + 1
}
// {a=2, b=1}
// the functional way
val counts2 = listOf("a", "b", "a").groupingBy { it }.eachCount()
Common mistakes
- Using a mutable list when a read-only one would do (mutability invites bugs).
- Chaining
filterthenmapover a huge list repeatedly — for very large data, useasSequence()to process lazily. - Reaching into a map with
map[key]!!— handle the missing-key (null) case.
Summary: Pick List/Set/Map by need, prefer read-only, and replace manual loops withfilter/map/groupBychains for clear, safe data transformations.