ForEach On Range

ID

kotlin.foreach_on_range

Severity

low

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Code Smell

Language

Kotlin

Tags

best-practice, performance

Description

Reports forEach calls on IntRange, LongRange, CharRange, and related progression types. Iterating a range with forEach forces the JVM to allocate an Iterator that boxes each primitive value, whereas a for loop over the same range compiles to a primitive counter loop with no heap allocation.

Rationale

In Kotlin, (1..10).forEach { …​ } calls Iterable<Int>.forEach, which requires an Iterator<Int> backed by boxed Int objects. A for loop over the same range uses the specialized IntIterator protocol and is compiled directly to a JVM bytecode for counter — no Iterator object is allocated and no boxing occurs. On hot paths this difference can be significant.

// Bad
(1..100_000).forEach { process(it) }
(1 until size).forEach { list.add(it) }

// Good
for (i in 1..100_000) process(i)
for (i in 1 until size) list.add(i)

Remediation

Replace the forEach call with a for loop. The transformation is mechanical and preserves all semantics.