Kotlin
forEach
index
programming
tutorial

How to get the current index in for each Kotlin

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Kotlin provides several ways to iterate collections, and choosing the right one matters when you need the current index. The plain forEach function gives only values, while index-aware alternatives keep code concise and safe. Understanding these options helps you avoid awkward workarounds and off-by-one mistakes.

Use forEachIndexed for Value Plus Index

forEachIndexed is the most direct approach for many cases.

kotlin
1val names = listOf("Ana", "Ben", "Cara")
2
3names.forEachIndexed { index, value ->
4    println("$index -> $value")
5}

This style is readable when you process value and index together, such as rendering numbered items.

Use withIndex in a for Loop

For more control, withIndex works well with a regular for loop.

kotlin
1val scores = listOf(88, 91, 73)
2
3for ((index, score) in scores.withIndex()) {
4    println("position=$index score=$score")
5}

This pattern can be easier to debug because break and continue are natural in a for loop.

Avoid Manual Index Tracking When Possible

You can track index manually, but it is usually less safe.

kotlin
1val items = listOf("a", "b", "c")
2var i = 0
3items.forEach {
4    println("$i -> $it")
5    i += 1
6}

This works, but mutable counters are error-prone if logic becomes complex. Prefer built-in index-aware iteration.

Handling Mutable Lists

When updating elements by index, use indexed loops rather than mutating inside forEach.

kotlin
1val numbers = mutableListOf(1, 2, 3, 4)
2
3for (index in numbers.indices) {
4    numbers[index] = numbers[index] * 10
5}
6
7println(numbers) // [10, 20, 30, 40]

Mutating the same list inside forEachIndexed can be safe in simple cases, but indexed loops communicate intent more clearly for in-place updates.

Duplicates and Why indexOf Is Misleading

A common anti-pattern is iterating values and calling indexOf to recover index. This breaks with duplicates because indexOf returns the first match.

kotlin
1val letters = listOf("a", "b", "a")
2
3letters.forEach { value ->
4    println("value=$value indexOf=${letters.indexOf(value)}")
5}

The final a still prints index zero. Use forEachIndexed when true position matters.

Sequences and Index Awareness

When working with Sequence, you can still use withIndex, but remember evaluation is lazy.

kotlin
1val seq = sequenceOf("x", "y", "z")
2
3val result = seq.withIndex()
4    .filter { (index, _) -> index % 2 == 0 }
5    .map { (_, value) -> value.uppercase() }
6    .toList()
7
8println(result) // [X, Z]

Lazy pipelines are efficient for large data sets, but avoid complex index-heavy pipelines if readability drops.

Arrays and Java Interop

Arrays and primitive arrays support index-aware iteration as well.

kotlin
1val values = intArrayOf(5, 10, 15)
2values.forEachIndexed { idx, item ->
3    println("index=$idx item=$item doubled=${item * 2}")
4}

This is useful when APIs return arrays instead of lists. The same indexing principles apply, and it keeps interop code straightforward.

For performance sensitive loops over very large collections, benchmark alternatives in your specific workload. In many apps the readability difference matters more than micro-optimization, so choose the iteration style your team can maintain confidently.

Common Pitfalls

  • Using forEach and then trying to recover index via expensive indexOf calls.
  • Mutating a collection structure while iterating, which can trigger concurrent modification errors.
  • Assuming one-based index in Kotlin collections, which are zero-based.
  • Overusing destructuring in long lambdas and making logic hard to read.
  • Choosing forEachIndexed when you actually need break or continue semantics.

Summary

  • Use forEachIndexed for straightforward index plus value iteration.
  • Use withIndex and for when you need control flow like break and continue.
  • Prefer built-in index tools over manual counters.
  • Use indexed loops for clear in-place mutation logic.
  • Keep index-based code readable with descriptive variable names.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.