Computers are brilliant at doing the same thing many times without getting bored. Printing a times table, adding up a list of prices, checking every email in a mailing list or retrying a download until it succeeds are all jobs for a loop.
Kotlin's main loop is for, and it works hand in hand with ranges: compact descriptions of sequences of numbers, like 1..10 for one to ten. Ranges can count up or down, skip numbers with step, and stop before the end with until. There are also while loops for repeating until a condition changes, and a tidy repeat(n) for doing something a fixed number of times.
In this lesson you'll loop over ranges and lists, count down and in steps, use while and do-while, and control loops with break and continue.
for loops and ranges
for (i in 1..5) {
println(i) // 1, 2, 3, 4, 5
}1..5is a range that includes both ends.for (x in something)visits each item, giving it the namex.- The loop variable is created fresh each time; you don't declare or increase it yourself.
| Range | Values |
|---|---|
1..5 | 1, 2, 3, 4, 5 |
1 until 5 or 1..<5 | 1, 2, 3, 4 |
5 downTo 1 | 5, 4, 3, 2, 1 |
0..10 step 2 | 0, 2, 4, 6, 8, 10 |
'a'..'e' | a, b, c, d, e |
Looping over collections
for works with any collection, not just numbers:
val fruits = listOf("apple", "pear", "plum")
for (fruit in fruits) println(fruit)
for (i in fruits.indices) println("$i: ${fruits[i]}")
for ((i, fruit) in fruits.withIndex()) println("${i + 1}. $fruit")indices is the range of valid positions, 0 until size. withIndex() gives the position and the item together, unpacked into two names with brackets. This is safer than counting positions by hand, which risks going one past the end.
while, do-while and repeat
A while loop repeats as long as its condition is true, which suits situations where you don't know in advance how many times it will run:
var balance = 100.0
var years = 0
while (balance < 200) {
balance *= 1.05
years++
}do { } while (condition) always runs its body at least once before checking. repeat(3) { println("Hip hip, hooray!") } runs a block a fixed number of times, with the count available as it, starting at 0.
break, continue and labels
breakstops the loop immediately.continueskips the rest of this pass and moves on to the next item.
In nested loops, break only leaves the innermost loop. To leave an outer loop, give it a label with name@ and use break@name:
outer@ for (row in 1..3) {
for (col in 1..3) {
if (row * col == 4) break@outer
print("${row * col} ")
}
}Ranges are values you can store and test
A range isn't only something to loop over. It's an ordinary value, so you can keep it in a variable, pass it to a function and ask it questions:
val teen = 13..19
println(15 in teen) // true
println(20 !in teen) // true
println(teen.first) // 13
println(teen.last) // 19
println(teen.count()) // 7
println(teen.sum()) // 112in checks membership without looping, so age in 13..19 is a tidy replacement for age >= 13 && age <= 19. Ranges of Double work for this kind of check too, as in 0.5 in 0.0..1.0, but you can't loop over them, because there's no obvious "next" decimal number.
When you add step, the last value is the last one the steps actually reach, not necessarily the end you wrote. (1..10 step 4).toList() is [1, 5, 9], so its last is 9. A range written backwards, such as 5..1, is simply empty: (5..1).isEmpty() is true, which is why the loop over it never runs. Use reversed() or downTo when you want to go the other way.
A for loop works over anything that can hand out its items one at a time. That includes strings, which give you each Char, and maps, which give you entries you can unpack into a key and a value:
for (ch in "abc") print(ch.uppercaseChar()) // ABC
for ((name, age) in mapOf("Ana" to 30, "Ben" to 25)) {
println("$name is $age")
}Finally, the loop variable is read-only. Writing i = 5 inside for (i in 1..3) is a compile error, because each pass gets a fresh val. If you need a counter you can change, use a while loop with a var.
Kotlin Loops Syntax
Loops
for (i in 1..10) { }
for (i in 0 until n) { } // or 0..<n
for (i in 10 downTo 0 step 2) { }
for (item in list) { }
for ((i, item) in list.withIndex()) { }
while (cond) { }
do { } while (cond)
repeat(3) { println(it) }
outer@ for (...) { break@outer }Kotlin Loops Summary
for (x in range)loops over each value;1..5includes both ends.until(or..<) excludes the end,downTocounts down andstepskips values.- Loop over lists directly, with
indices, or withwithIndex()for position and item. whilechecks first;do-whileruns at least once;repeat(n)runs a block n times.breakends a loop,continueskips to the next pass, and labels control outer loops.
Kotlin Loops Examples
Each example shows the code, the output it produces and what each part does.
A times table and a countdown
fun main() {
val n = 7
for (i in 1..5) {
println("$n x $i = ${n * i}")
}
for (s in 10 downTo 0 step 5) {
print("$s ")
}
println("Liftoff!")
}7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
10 5 0 Liftoff!Line-by-line explanation
- Line 31..5 includes both 1 and 5.
- Line 6downTo counts down, and step 5 jumps by five each time.
- Line 9println finishes the countdown line.
Totals with a list and withIndex
fun main() {
val prices = listOf(2.50, 4.00, 1.25)
var total = 0.0
for ((i, price) in prices.withIndex()) {
println("Item ${i + 1}: £$price")
total += price
}
println("Total: £$total")
for (i in 0 until prices.size) {
if (prices[i] < 2.0) println("Item ${i + 1} is cheap")
}
}Item 1: £2.5
Item 2: £4.0
Item 3: £1.25
Total: £7.75
Item 3 is cheapLine-by-line explanation
- Line 4withIndex gives the position and the value together.
- Line 5Doubles print without trailing zeros, as 2.5, not 2.50; use "%.2f".format for money.
- Line 10until stops before prices.size, so the index never goes out of range.
while, repeat, break and continue
fun main() {
var savings = 1000.0
var years = 0
while (savings < 1500) {
savings *= 1.1
years++
}
println("Years to reach 1500: $years")
repeat(3) { println("Attempt ${it + 1}") }
for (n in 1..10) {
if (n % 2 == 0) continue
if (n > 7) break
print("$n ")
}
println()
}Years to reach 1500: 5
Attempt 1
Attempt 2
Attempt 3
1 3 5 7 Line-by-line explanation
- Lines 4 to 7Grow by 10% a year until savings reach 1500: 1100, 1210, 1331, 1464.1 and then 1610.51, after 5 years.
- Line 10repeat runs the block three times; it counts from 0.
- Line 13continue skips even numbers.
- Line 14break stops the loop as soon as n passes 7.
Common Kotlin Loops Mistakes
Expecting until to include the end
for (i in 1 until 5) print(i) // 1234, not 12345for (i in 1..5) print(i) // 12345Counting down with ..
for (i in 5..1) print(i) // prints nothing: the range is emptyfor (i in 5 downTo 1) print(i) // 54321A while loop that never ends
var tries = 0
while (tries < 3) {
println("Trying") // tries never changes
}var tries = 0
while (tries < 3) {
println("Trying")
tries++
}Kotlin Loops in Real Projects
Loops in apps
Apps loop over lists of messages to display them, over shopping cart items to total the price, and over files to process them. Games run a loop for every frame. In real Kotlin code you'll often use collection functions like forEach, map and filter, covered in the collection operations lesson, which replace many hand-written loops with a single line.
Kotlin Loops FAQ
How do I loop with an index in Kotlin?
Use for ((i, item) in list.withIndex()) to get the position and the item together, or for (i in list.indices) if you only need positions. Both avoid writing 0 until list.size by hand, and indices is automatically empty for an empty list.
What is the difference between until and .. in Kotlin?
1..5 includes both ends, giving 1 to 5. 1 until 5, also written 1..<5, stops before the end, giving 1 to 4. The exclusive form is the natural choice when looping over positions, because the last valid index is always one less than the size.
Can I remove items from a list while looping over it?
Not with a plain for loop over a MutableList: changing the list while you're iterating over it usually throws a ConcurrentModificationException. Use list.removeAll { it % 2 == 0 } to remove matching items in one go, or build a new list with filter.
How do I skip to the next item in a forEach?
continue and break only work in real loops such as for and while. Inside forEach { }, return@forEach ends the current item's lambda and moves on to the next one, which acts like continue. If you need break, switch to a for loop.
How do I check if a number is between two values in Kotlin?
Use a range with in: if (score in 0..100) is true for 0, 100 and everything between. For an upper bound that should be excluded, write score in 0..<100. To force a value into a range instead of checking it, use coerceIn: 150.coerceIn(0, 100) is 100.
Kotlin Loops Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the loop so it prints 10, 9, 8 ... 1.
for (i in 10 1) println(i)
How many numbers does for (i in 0 until 4) loop over?
What does this print?
for (i in 1..10 step 3) print("$i ")
Which loop always runs its body at least once?
What does this print?
var total = 0
for (n in 1..6) {
if (n == 4) continue
total += n
}
println(total)
Kotlin Loops Quiz
5 questions to check what you learned.
Does the range
1..3include 3?- No
- Yes
- Only in while loops
- Only with step
What does
repeat(4) { }do?- Runs the block four times, with it from 0 to 3
- Repeats the program four times
- Creates a list of four items
- Waits four seconds
What does
continuedo inside a loop?- Skips the rest of this pass and starts the next one
- Ends the loop
- Restarts from the first item
- Pauses the program
How do you leave an outer loop from inside an inner loop?
- break twice
- Label the outer loop, such as outer@, and use break@outer
- return@inner
- It isn't possible
What does
for (i in 5..1)do?- Counts down from 5 to 1
- Throws an exception
- Nothing: the range is empty
- Counts up from 1 to 5