Theory
Two lists, two rules
FestConnect Mobile has two collections with different needs. The list of EVENTS, once loaded, should NOT change during a session: it is fixed. The list of REGISTRATIONS grows as people sign up: it must change.
Kotlin handles this with a deliberate distinction that echoes val vs var: some collections are READ-ONLY, others MUTABLE, and you CHOOSE based on whether the data should change. This lesson covers Kotlin's arrays and, more importantly, its lists, where the read-only versus mutable choice is a small but meaningful design decision the language makes you take.
Theory
Arrays: fixed size
An array has a FIXED size, set at creation:
val nums = arrayOf(1, 2, 3) (or intArrayOf(1, 2, 3) for a primitive int array)
Access by index (0-based): nums[0] is 1; you can CHANGE an element (nums[0] = 5) but NOT add or remove (the length is fixed). .size gives the count.
Arrays are useful when the size is known and fixed, but for most app data (lists that grow), you will reach for LISTS instead, exactly as you preferred ArrayList over arrays in Java for flexible collections.
Theory
Lists: read-only vs mutable
Kotlin lists come in TWO kinds, and choosing is the key idea:
- listOf(...) creates a READ-ONLY (immutable) list: you can READ it but NOT add, remove, or change elements
- mutableListOf(...) creates a MUTABLE list:
.add(),.remove(),.removeAt(), andlist[i] = xall work
This mirrors val vs var: prefer READ-ONLY by default (safer, clearer intent), use mutable only when the data genuinely changes.
val events = listOf("Garba", "Coding") cannot grow; val regs = mutableListOf<String>() can. Both use 0-based list[i] access and .size. (Maps and Sets follow the same read-only/mutable pattern: mapOf/mutableMapOf.)
Practical
Read-only events, mutable registrations
fun main() {
// READ-ONLY list: cannot be modified
val events = listOf("Garba Night", "Coding Contest")
println(events[0]) // Garba Night (0-based access)
println(events.size) // 2
// events.add("Webinar") // COMPILE ERROR: listOf is read-only
// MUTABLE list: can add/remove/change
val regs = mutableListOf("Riya")
regs.add("Aman") // ok
regs.add("Zoya")
regs.removeAt(0) // removes "Riya"
println(regs) // [Aman, Zoya]
println(regs.size) // 2
}
Quiz
You create a list with listOf("Garba", "Coding") and try to call .add() on it. What happens?
- It adds the item successfully
- A COMPILE ERROR: listOf creates a READ-ONLY list; use mutableListOf if you need to add or remove items
- A runtime crash only when the app runs
- It silently ignores the add
Show the answer
A COMPILE ERROR: listOf creates a READ-ONLY list; use mutableListOf if you need to add or remove items
listOf creates a READ-ONLY (immutable) list, which has no add/remove operations, so calling .add() is a COMPILE ERROR, caught before the program runs. To create a list you can modify, use mutableListOf, which provides add, remove, removeAt, and index assignment. This read-only-vs-mutable distinction mirrors val vs var and lets the compiler enforce your intent: if a list should not change, listOf guarantees it. Option A is wrong (read-only lists reject add). Option C misplaces the error at runtime; Kotlin catches it at COMPILE time (the read-only type simply lacks add). Option D invents silent behaviour. Choose listOf for fixed data, mutableListOf for changing data.
Think first
Why prefer read-only collections?
You could just use mutableListOf everywhere and never worry about which to pick. Why does Kotlin encourage read-only listOf by default? Then tap.
Show the answer
For the same reasons val is preferred over var: SAFETY and CLARITY. A read-only list GUARANTEES the data will not change, so you (and the compiler, and other developers reading your code) can rely on that: no accidental modification, no surprise when a list you passed to another function comes back changed. It makes INTENT explicit: listOf says 'this is fixed', mutableListOf says 'this will change'. This prevents a whole class of bugs where shared mutable data is modified unexpectedly, and makes code easier to reason about. Use mutableListOf only where the data GENUINELY needs to change (like the growing registrations list); default to read-only everywhere else. The discipline, immutable by default, mutable by necessity, is a hallmark of safer modern code, and Kotlin builds it into the collections.
Watch out
Array and list traps
Trying to add to a listOf: it is read-only; use mutableListOf.
Trying to resize an array: arrays are fixed-size; use a list to grow.
Defaulting to mutable: prefer listOf (read-only) unless the data must change.
Index out of bounds: list[i] with i >= size throws; the last index is size - 1.
val list still allows mutation if the list is mutable: val means the VARIABLE cannot be reassigned; a mutableListOf assigned to a val can still be modified (its CONTENTS change, the reference does not).
Theory
Collections ready; now iterate them
FestConnect Mobile can hold its events (read-only) and registrations (mutable). To DO something with each item, print them, count them, filter them, you need LOOPS. The final Kotlin-basics lesson covers for and while loops, and the control keywords break, continue and return. Then Unit 2 turns this data and logic into proper CLASSES, building FestConnect Mobile's object-oriented structure in Kotlin.
Summary
Key takeaways
- Arrays have a FIXED size: arrayOf(1,2,3); access by 0-based index (arr[0]); elements changeable, length not.
- Lists come in two kinds: listOf(...) is READ-ONLY (immutable); mutableListOf(...) is MUTABLE (add/remove/set).
- This read-only vs mutable split mirrors val vs var; prefer read-only by default.
- Read-only lists allow reading (list[i], .size) but not modification (add on a listOf is a compile error).
- Mutable lists support .add(), .remove(), .removeAt(), and list[i] = x.
- A val holding a mutableListOf can still have its CONTENTS changed (the reference is fixed, not the list).
- Memory hook: arrays are fixed-size; listOf is read-only, mutableListOf can change (like val/var).