The for loop
A for loop runs a block of code once for every item of a collection, such as an array or a list. You name a variable, and on each pass it holds the next item:
val fruits = arrayOf("banana", "orange", "pear", "kiwi")
for (fruit in fruits) {
println("I eat $fruit")
}
The output is:
I eat banana
I eat orange
I eat pear
I eat kiwi
The same four lines of code would have taken four println calls with indices. Now the loop handles any number of fruits, including none.
The parts of the loop
forstarts the loop.fruitis the loop variable. On the first pass it is"banana", on the second"orange", and so on. You choose the name.inseparates the loop variable from the collection. Other languages use a colon here. Kotlin reads like English: "for each fruit in fruits".fruitsis the collection being looped over.- The block between
{and}is the body. It runs once per item.
The loop variable needs no val or var and no type. Kotlin declares it for you and works out the type from the collection, so here fruit is a String. It is read-only inside the body: you cannot assign a new value to it.
String templates
Inside the body, "I eat $fruit" is a string template. The $ followed by a name inserts that variable's value into the text. For anything more complex than a name, wrap it in braces: "${fruit.length} letters". To print a literal dollar sign, escape it as \$.
The exercise
The starting code has an array of friends:
val friends = arrayOf("Andy", "Mary", "John")
The task is to greet each friend with a loop, in two steps:
- Write the loop. Use
forwith a variable namedfriendand loop through thefriendsarray:for (friend in friends) { }. The names are different on purpose:friendsis the whole array, andfriendis one item of it. - Print inside the body. For every
friend, printHey,followed by the name and an exclamation mark. A template does this in one line:println("Hey, $friend!").
val friends = arrayOf("Andy", "Mary", "John")
for (friend in friends) {
println("Hey, $friend!")
}
The output is:
Hey, Andy!
Hey, Mary!
Hey, John!
The template stops reading the name at the !, because an exclamation mark cannot be part of a variable name. A letter would not stop it. That is the reason for the braces: "$friendly" looks for a variable named friendly, while "${friend}ly" uses friend.
Other ways to loop
Sometimes you need the position of each item as well as the item. Kotlin gives two common ways:
for (i in friends.indices) {
println("$i ${friends[i]}")
}
for ((i, friend) in friends.withIndex()) {
println("$i $friend")
}
Both print each friend with its index, starting at 0. The property indices is the range of valid indices, 0 to size - 1, so the loop cannot run past the end. A loop also works on a number range: for (x in 1..3) visits 1, 2 and 3, since .. includes both ends. Use 0 until n when the end should be left out.
Common mistakes
- Using a colon.
for (friend : friends)is Java syntax. Kotlin usesin. - Declaring the loop variable. Writing
val friendorString friendinside the parentheses is an error. - Printing outside the body. A statement after the closing brace runs once, after the loop, and cannot see the loop variable.
- Looping to
sizeby index.for (i in 0..friends.size)includes the indexfriends.size, which does not exist, and throws anArrayIndexOutOfBoundsException. Loop over the items directly, or useindices. - Changing a list while looping over it. Adding to or removing from a list inside a
forloop over that list usually throws aConcurrentModificationException.
Key takeaways
for (item in collection) { ... }runs the body once per item.- The loop variable is declared by the loop itself and is read-only.
- Use
$nameor${expression}to put values in strings. - Use
indicesorwithIndex()when you need the position as well.