Lists, Sets & Maps
A single variable holds one value. Real programs handle many: all the items in a shopping cart, every student in a class, the stock count of each product. Kotlin gives you three main collections for this: lists, sets and maps.
Each comes in two flavours: a read-only version that cannot be changed after it is created, and a mutable version that can. In this lesson you will create and use all of them, and learn which one to choose.
The three collection types
| Collection | What it holds | Read-only | Mutable |
|---|---|---|---|
| List | items in order, duplicates allowed | listOf(...) | mutableListOf(...) |
| Set | unique items, no duplicates | setOf(...) | mutableSetOf(...) |
| Map | key-value pairs, unique keys | mapOf(k to v) | mutableMapOf(k to v) |
As with val and var, prefer the read-only versions and use mutable ones only when the contents really need to change.
Lists
A list keeps items in order. Each item has an index, starting at 0.
fun main() {
val cities = listOf("Rohtak", "Jaipur", "Pune", "Kochi")
println(cities)
println(cities.size)
println(cities[1])
println(cities.first() + " to " + cities.last())
println("Pune" in cities)
println(cities.indexOf("Kochi"))
println(cities.getOrNull(10))
println(cities.subList(1, 3))
}[Rohtak, Jaipur, Pune, Kochi] 4 Jaipur Rohtak to Kochi true 3 null [Jaipur, Pune]
Printing a list shows its items in square brackets. cities[10] would crash with an IndexOutOfBoundsException, so getOrNull(10) is the safe choice when an index might be invalid. subList(1, 3) takes indexes 1 and 2.
A read-only List has no add or remove functions at all, so you cannot change it by mistake.
Mutable lists
A MutableList adds functions that change it: add, remove, removeAt, clear, and assignment by index.
fun main() {
val cart = mutableListOf("Rice", "Dal")
cart.add("Ghee")
cart.add(0, "Atta")
cart += "Salt"
println(cart)
cart.remove("Dal")
cart[1] = "Basmati Rice"
println(cart)
cart.removeAt(cart.lastIndex)
println(cart)
println(cart.size)
}[Atta, Rice, Dal, Ghee, Salt] [Atta, Basmati Rice, Ghee, Salt] [Atta, Basmati Rice, Ghee] 3
Notice that cart is a val, yet its contents change. val only means the variable always points to the same list; the list itself is mutable. add(0, "Atta") inserts at the front, and cart += "Salt" is a short way to write cart.add("Salt").
Kotlin also has handy ways to build lists:
fun main() {
val squares = List(5) { it * it }
println(squares)
val seats = MutableList(3) { "free" }
seats[1] = "booked"
println(seats)
val isWeekend = true
val menu = buildList {
add("Idli")
add("Dosa")
if (isWeekend) add("Pongal")
}
println(menu)
}[0, 1, 4, 9, 16] [free, booked, free] [Idli, Dosa, Pongal]
List(5) { it * it } creates five items, calling the lambda with each index. buildList lets you add items step by step, with conditions, and gives back a read-only list at the end.
Sets
A set keeps each value only once. Adding a value that is already there does nothing. Sets are ideal for removing duplicates and for fast "is this in the group?" checks. Kotlin's default sets remember the order in which items were added.
fun main() {
val visitors = listOf("Aarav", "Isha", "Aarav", "Kabir", "Isha")
val unique = visitors.toSet()
println(unique)
println(unique.size)
val cricket = setOf("Aarav", "Kabir", "Rohan")
val chess = setOf("Kabir", "Meera", "Rohan")
println(cricket intersect chess)
println(cricket union chess)
println(cricket subtract chess)
val tags = mutableSetOf("kotlin")
println(tags.add("android"))
println(tags.add("kotlin"))
println(tags)
}[Aarav, Isha, Kabir] 3 [Kabir, Rohan] [Aarav, Kabir, Rohan, Meera] [Aarav] true false [kotlin, android]
intersect finds students who play both games, union combines everyone without repeats, and subtract finds those who play only cricket. add returns true if the item was new and false if it was already present.
Maps
A map stores key-value pairs, like a phone book (name to number) or a price list (item to price). Each key appears once. You create pairs with the word to, and look up values with square brackets.
fun main() {
val stock = mutableMapOf("pen" to 40, "notebook" to 25)
stock["eraser"] = 60
stock["pen"] = 35
println(stock)
println(stock["notebook"])
println(stock["stapler"])
println(stock.getOrDefault("stapler", 0))
println(stock.keys)
println(stock.values.sum())
for ((item, qty) in stock) {
println("$item: $qty")
}
stock.remove("eraser")
println("eraser" in stock)
}{pen=35, notebook=25, eraser=60}
25
null
0
[pen, notebook, eraser]
120
pen: 35
notebook: 25
eraser: 60
falseImportant details:
- Printing a map shows
{key=value, ...}. stock["stapler"]returnsnullfor a missing key, so the result type isInt?. UsegetOrDefault,?: 0, orgetValue(which throws an exception if the key is missing).- Assigning to an existing key, like
stock["pen"] = 35, replaces the old value. for ((item, qty) in stock)unpacks each entry into its key and value.
Counting with a map, and Pair
A very common job is counting how often something appears. "Aarav" to 91 creates a Pair, a small object holding two values called first and second.
fun main() {
val votes = listOf("Biryani", "Dosa", "Biryani", "Chole", "Dosa", "Biryani")
val count = mutableMapOf<String, Int>()
for (dish in votes) {
count[dish] = (count[dish] ?: 0) + 1
}
println(count)
val topper = "Aarav" to 91
println(topper)
println(topper.first)
}{Biryani=3, Dosa=2, Chole=1}
(Aarav, 91)
AaravmutableMapOf<String, Int>() creates an empty map; because it starts empty, you write the key and value types in angle brackets. In the next lesson you will see that votes.groupingBy { it }.eachCount() does this counting in one line.
Common mistakes
- Expecting
listOfto allowadd. UsemutableListOfwhen the list must change, or create a new list withlist + item. - Thinking read-only means frozen. A read-only
Listview can point to a list that other code still changes. If you need a snapshot, copy it withtoList(). - Forgetting that map lookups can be
null.stock["pen"] + 1does not compile; handle thenullfirst. - Using a list for membership checks on big data.
inon a list checks every item; a set answers much faster.
Key points
- Lists are ordered and allow duplicates; sets keep unique values; maps store key-value pairs.
listOf,setOfandmapOfcreate read-only collections; themutable...Ofversions can change.valwith a mutable collection fixes the reference, not the contents.list[i],getOrNull,first(),last()andinread lists safely.map[key]returns a nullable value;tocreates aPairfor map entries.- Arrays exist but lists are the everyday choice; print arrays with
contentToString().
Exercise
A school canteen recorded the snacks sold in one break: "samosa", "juice", "samosa", "sandwich", "juice", "samosa". Prices are samosa Rs 15, juice Rs 20 and sandwich Rs 30, stored in a map. Count how many of each snack were sold, print the counts, then print the total earnings by looking up each snack's price.
Show solution
fun main() {
val sold = listOf("samosa", "juice", "samosa", "sandwich", "juice", "samosa")
val prices = mapOf("samosa" to 15, "juice" to 20, "sandwich" to 30)
val counts = mutableMapOf<String, Int>()
for (snack in sold) {
counts[snack] = (counts[snack] ?: 0) + 1
}
println(counts)
var total = 0
for ((snack, qty) in counts) {
total += qty * prices.getValue(snack)
}
println("Total: Rs $total")
}{samosa=3, juice=2, sandwich=1}
Total: Rs 115getValue returns a plain Int because every snack sold has a price; if one were missing, it would throw an exception instead of silently using null.
Quick Quiz
1. Which collection automatically removes duplicates?
A set keeps each value only once.
2. What does mapOf("a" to 1)["b"] return?
A missing key gives null; the result type is nullable.
3. val names = mutableListOf("Isha"). Is names.add("Rohan") allowed?
val stops reassignment of the variable, not changes to a mutable list.
4. How do you print the items of an IntArray called a?
Printing an array directly shows a type code and hash; contentToString() shows the items.
Learn Kotlin with a mentor
Free lessons get you started. Our Programming & Software Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
