Loops
Overview
Kotlin provides multiple loop structures for repeatedly executing code blocks, including for loops, while loops, and do-while loops. Kotlin's loop statements are powerful, supporting ranges, collection iteration, and various control flow operations.
for Loops
Basic for Loop
kotlin
fun main() {
// Iterate over a range
println("Basic for loop:")
for (i in 1..5) {
println("Number: $i")
}
// Iterate over character range
println("\nCharacter range:")
for (c in 'a'..'e') {
println("Character: $c")
}
// Using until (exclusive of end value)
println("\nuntil loop:")
for (i in 1 until 5) {
println("Number: $i")
}
// Descending loop
println("\nDescending loop:")
for (i in 5 downTo 1) {
println("Countdown: $i")
}
// Specifying step
println("\nWith step:")
for (i in 1..10 step 2) {
println("Odd: $i")
}
for (i in 10 downTo 1 step 3) {
println("Descending step 3: $i")
}
}Iterating Collections
kotlin
fun main() {
val fruits = listOf("Apple", "Banana", "Orange", "Grape")
val numbers = arrayOf(1, 2, 3, 4, 5)
val map = mapOf("a" to 1, "b" to 2, "c" to 3)
// Iterate over list
println("Iterate over list:")
for (fruit in fruits) {
println("Fruit: $fruit")
}
// Iterate over array
println("\nIterate over array:")
for (number in numbers) {
println("Number: $number")
}
// Iterate with index
println("\nIterate with index:")
for ((index, fruit) in fruits.withIndex()) {
println("$index: $fruit")
}
// Iterate over map
println("\nIterate over map:")
for ((key, value) in map) {
println("$key -> $value")
}
// Iterate over keys only
println("\nIterate over keys:")
for (key in map.keys) {
println("Key: $key")
}
// Iterate over values only
println("\nIterate over values:")
for (value in map.values) {
println("Value: $value")
}
}Nested Loops
kotlin
fun main() {
// Print multiplication table
println("Multiplication table:")
for (i in 1..9) {
for (j in 1..i) {
print("${j}×${i}=${i*j}\t")
}
println()
}
// 2D array iteration
val matrix = arrayOf(
arrayOf(1, 2, 3),
arrayOf(4, 5, 6),
arrayOf(7, 8, 9)
)
println("\nMatrix iteration:")
for (row in matrix) {
for (element in row) {
print("$element\t")
}
println()
}
// 2D iteration with index
println("\nMatrix iteration with index:")
for ((rowIndex, row) in matrix.withIndex()) {
for ((colIndex, element) in row.withIndex()) {
println("matrix[$rowIndex][$colIndex] = $element")
}
}
}while Loops
Basic while Loop
kotlin
fun main() {
// Basic while loop
var count = 1
println("while loop:")
while (count <= 5) {
println("Count: $count")
count++
}
// Complex condition while loop
var number = 1
println("\nPowers of 2:")
while (number <= 100) {
println("2^${kotlin.math.log2(number.toDouble()).toInt()} = $number")
number *= 2
}
// User input simulation
val inputs = listOf("hello", "world", "quit", "more")
var inputIndex = 0
println("\nSimulated user input:")
while (inputIndex < inputs.size) {
val input = inputs[inputIndex]
println("Input: $input")
if (input == "quit") {
println("Exiting program")
break
}
inputIndex++
}
}do-while Loop
kotlin
fun main() {
// do-while loop (executes at least once)
var attempts = 0
val maxAttempts = 3
println("do-while loop example:")
do {
attempts++
println("Attempt $attempts")
// Simulate some condition check
val success = attempts >= 2 // Success on 2nd attempt
if (success) {
println("Operation successful!")
break
} else {
println("Operation failed, retrying...")
}
} while (attempts < maxAttempts)
if (attempts >= maxAttempts) {
println("Maximum attempts reached")
}
// Menu system example
val menuOptions = listOf("1. View", "2. Add", "3. Delete", "0. Exit")
val userChoices = listOf("1", "2", "invalid", "0") // Simulated user choices
var choiceIndex = 0
println("\nMenu system:")
do {
println("\nPlease select an operation:")
menuOptions.forEach { println(it) }
val choice = if (choiceIndex < userChoices.size) {
userChoices[choiceIndex++]
} else {
"0"
}
println("Your choice: $choice")
when (choice) {
"1" -> println("Executing view operation")
"2" -> println("Executing add operation")
"3" -> println("Executing delete operation")
"0" -> println("Exiting system")
else -> println("Invalid choice, please try again")
}
} while (choice != "0")
}Loop Control Statements
break and continue
kotlin
fun main() {
// break example
println("break example - find first even number:")
for (i in 1..10) {
if (i % 2 == 0) {
println("Found first even number: $i")
break
}
println("Checking: $i")
}
// continue example
println("\ncontinue example - skip even numbers:")
for (i in 1..10) {
if (i % 2 == 0) {
continue // Skip even numbers
}
println("Odd: $i")
}
// break and continue in nested loops
println("\nControl in nested loops:")
for (i in 1..3) {
println("Outer loop: $i")
for (j in 1..5) {
if (j == 3) {
println(" Skipping inner $j")
continue
}
if (j == 4) {
println(" Inner loop ended early")
break
}
println(" Inner loop: $j")
}
}
}Labels and Jumps
kotlin
fun main() {
// Using labels to control nested loops
println("Label jump example:")
outer@ for (i in 1..3) {
inner@ for (j in 1..3) {
if (i == 2 && j == 2) {
println("Breaking outer loop at ($i, $j)")
break@outer // Break out of outer loop
}
println("($i, $j)")
}
}
println("\nLabel continue example:")
outer@ for (i in 1..3) {
for (j in 1..3) {
if (j == 2) {
println("Continue outer loop at ($i, $j)")
continue@outer // Continue to next iteration of outer loop
}
println("($i, $j)")
}
}
}Functional Loop Operations
forEach and Other Higher-Order Functions
kotlin
fun main() {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// forEach
println("forEach:")
numbers.forEach { number ->
println("Number: $number")
}
// forEachIndexed
println("\nforEachIndexed:")
numbers.forEachIndexed { index, number ->
println("Index $index: $number")
}
// map - transform each element
println("\nmap - square:")
val squares = numbers.map { it * it }
println(squares)
// filter - filter elements
println("\nfilter - even numbers:")
val evens = numbers.filter { it % 2 == 0 }
println(evens)
// Chain operations
println("\nChained operations - squares of even numbers:")
val evenSquares = numbers
.filter { it % 2 == 0 }
.map { it * it }
println(evenSquares)
// reduce - aggregation
println("\nreduce - sum:")
val sum = numbers.reduce { acc, number -> acc + number }
println("Total: $sum")
// fold - aggregation with initial value
println("\nfold - product with initial value:")
val product = numbers.fold(1) { acc, number -> acc * number }
println("Product: $product")
}repeat Function
kotlin
fun main() {
// repeat function
println("repeat function:")
repeat(5) { index ->
println("Repeat $index times")
}
// Practical application: Retry mechanism
fun simulateNetworkCall(): Boolean {
return kotlin.random.Random.nextBoolean()
}
println("\nRetry mechanism example:")
var success = false
repeat(3) { attempt ->
println("Attempt ${attempt + 1} network request")
success = simulateNetworkCall()
if (success) {
println("Request successful!")
return@repeat // Exit repeat early
} else {
println("Request failed")
}
}
if (!success) {
println("All retries failed")
}
}Practical Examples
Data Processing
kotlin
data class Student(val name: String, val age: Int, val grades: List<Int>)
fun main() {
val students = listOf(
Student("Alice", 20, listOf(85, 92, 78, 96)),
Student("Bob", 19, listOf(76, 84, 88, 79)),
Student("Charlie", 21, listOf(95, 89, 92, 98)),
Student("Diana", 20, listOf(82, 87, 85, 90))
)
println("Student grade analysis:")
// Calculate each student's average grade
for (student in students) {
val average = student.grades.average()
val grade = when {
average >= 90 -> "A"
average >= 80 -> "B"
average >= 70 -> "C"
else -> "D"
}
println("${student.name} (age ${student.age}): Average %.1f, Grade $grade".format(average))
}
// Find top student
var topStudent: Student? = null
var highestAverage = 0.0
for (student in students) {
val average = student.grades.average()
if (average > highestAverage) {
highestAverage = average
topStudent = student
}
}
println("\nTop student: ${topStudent?.name}, Average: %.1f".format(highestAverage))
// Count students by grade
val gradeCount = mutableMapOf("A" to 0, "B" to 0, "C" to 0, "D" to 0)
for (student in students) {
val average = student.grades.average()
val grade = when {
average >= 90 -> "A"
average >= 80 -> "B"
average >= 70 -> "C"
else -> "D"
}
gradeCount[grade] = gradeCount[grade]!! + 1
}
println("\nGrade statistics:")
for ((grade, count) in gradeCount) {
println("Grade $grade: $count students")
}
}Game Development Example
kotlin
class GameBoard(val size: Int) {
private val board = Array(size) { Array(size) { '.' } }
fun placeSymbol(row: Int, col: Int, symbol: Char): Boolean {
return if (isValidPosition(row, col) && board[row][col] == '.') {
board[row][col] = symbol
true
} else {
false
}
}
private fun isValidPosition(row: Int, col: Int): Boolean {
return row in 0 until size && col in 0 until size
}
fun display() {
println(" " + (0 until size).joinToString(" "))
for ((rowIndex, row) in board.withIndex()) {
print("$rowIndex ")
for (cell in row) {
print("$cell ")
}
println()
}
}
fun checkWin(symbol: Char): Boolean {
// Check rows
for (row in board) {
var count = 0
for (cell in row) {
if (cell == symbol) count++ else count = 0
if (count >= 3) return true
}
}
// Check columns
for (col in 0 until size) {
var count = 0
for (row in 0 until size) {
if (board[row][col] == symbol) count++ else count = 0
if (count >= 3) return true
}
}
// Check diagonals
for (startRow in 0 until size - 2) {
for (startCol in 0 until size - 2) {
var count = 0
for (i in 0 until 3) {
if (board[startRow + i][startCol + i] == symbol) {
count++
} else {
break
}
}
if (count >= 3) return true
}
}
return false
}
}
fun main() {
val game = GameBoard(5)
val moves = listOf(
Triple(0, 0, 'X'), Triple(0, 1, 'O'),
Triple(1, 1, 'X'), Triple(1, 2, 'O'),
Triple(2, 2, 'X'), Triple(2, 3, 'O')
)
println("Tic-tac-toe demo:")
game.display()
for ((row, col, symbol) in moves) {
println("\nPlayer $symbol places at ($row, $col)")
if (game.placeSymbol(row, col, symbol)) {
game.display()
if (game.checkWin(symbol)) {
println("Player $symbol wins!")
break
}
} else {
println("Invalid move!")
}
}
}Algorithm Implementation
kotlin
// Bubble sort
fun bubbleSort(arr: IntArray) {
val n = arr.size
for (i in 0 until n - 1) {
var swapped = false
for (j in 0 until n - i - 1) {
if (arr[j] > arr[j + 1]) {
// Swap elements
val temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
swapped = true
}
}
// If no swaps, already sorted
if (!swapped) break
}
}
// Binary search
fun binarySearch(arr: IntArray, target: Int): Int {
var left = 0
var right = arr.size - 1
while (left <= right) {
val mid = left + (right - left) / 2
when {
arr[mid] == target -> return mid
arr[mid] < target -> left = mid + 1
else -> right = mid - 1
}
}
return -1 // Not found
}
// Fibonacci sequence
fun fibonacci(n: Int): Long {
if (n <= 1) return n.toLong()
var prev = 0L
var curr = 1L
for (i in 2..n) {
val next = prev + curr
prev = curr
curr = next
}
return curr
}
fun main() {
// Sorting demo
val numbers = intArrayOf(64, 34, 25, 12, 22, 11, 90)
println("Before sorting: ${numbers.contentToString()}")
bubbleSort(numbers)
println("After sorting: ${numbers.contentToString()}")
// Binary search demo
val target = 25
val index = binarySearch(numbers, target)
if (index != -1) {
println("Found $target at index $index")
} else {
println("$target not found")
}
// Fibonacci sequence
println("\nFirst 10 Fibonacci numbers:")
for (i in 0..9) {
print("${fibonacci(i)} ")
}
println()
}Performance Optimization
Loop Optimization Tips
kotlin
fun main() {
val largeList = (1..1000000).toList()
// 1. Use appropriate loop type
// For simple iteration, forEach is often faster than traditional for loop
// 2. Avoid creating unnecessary objects in loops
// Bad practice
fun badExample() {
for (i in largeList) {
val result = "Number: $i" // Creates new string each time
// Process result...
}
}
// Good practice
fun goodExample() {
val sb = StringBuilder()
for (i in largeList) {
sb.clear()
sb.append("Number: ").append(i)
val result = sb.toString()
// Process result...
}
}
// 3. Use sequences for lazy evaluation
val result = largeList.asSequence()
.filter { it % 2 == 0 }
.map { it * it }
.take(10)
.toList()
println("First 10 squares of even numbers: $result")
// 4. Exit loops early
fun findFirst(predicate: (Int) -> Boolean): Int? {
for (item in largeList) {
if (predicate(item)) {
return item // Return immediately when found
}
}
return null
}
val firstLargeNumber = findFirst { it > 500000 }
println("First number greater than 500000: $firstLargeNumber")
}Best Practices
1. Choose the Right Loop Type
kotlin
fun main() {
val items = listOf("a", "b", "c", "d", "e")
// Simple iteration: use forEach
items.forEach { println(it) }
// Need index: use forEachIndexed or withIndex
items.forEachIndexed { index, item ->
println("$index: $item")
}
// Need transformation: use map
val upperCase = items.map { it.uppercase() }
// Need filtering: use filter
val filtered = items.filter { it != "c" }
// Complex logic: use traditional for loop
for (i in items.indices) {
if (i > 0 && items[i] == items[i-1]) {
// Complex adjacent element comparison logic
}
}
}2. Avoid Deep Nesting
kotlin
// Bad practice: Too deep nesting
fun badNestedLoops(matrix: Array<Array<Int>>) {
for (i in matrix.indices) {
for (j in matrix[i].indices) {
for (k in 0..10) {
if (matrix[i][j] == k) {
for (l in 0..5) {
// Too deep, hard to understand
}
}
}
}
}
}
// Good practice: Extract functions
fun goodNestedLoops(matrix: Array<Array<Int>>) {
for (i in matrix.indices) {
for (j in matrix[i].indices) {
processCell(matrix[i][j])
}
}
}
fun processCell(value: Int) {
for (k in 0..10) {
if (value == k) {
performOperation(k)
}
}
}
fun performOperation(k: Int) {
for (l in 0..5) {
// Specific operation
}
}Next Steps
After mastering loop statements, let's learn about function definition and usage in Kotlin, including higher-order functions and lambda expressions.
Next Chapter: Functions
Exercises
- Write a program to generate a multiplication table of specified size
- Implement a simple number guessing game using loops to handle user input
- Create a function to calculate statistics for all elements in an array (max, min, average, etc.)
- Implement selection sort algorithm and compare its performance with bubble sort
- Write a program to generate the first n rows of Pascal's triangle