Simplify Loops with Non-Local break and continue in Kotlin 2.1.0
Kotlin
Simplify Loops with Non-Local break and continue in Kotlin 2.1.0
Akshay Nandwana
January 8, 2025
5 min read
70 views

Kotlin 2.1 introduced non-local break and continue, a feature that enhances loop control in higher-order functions like forEach. If you've ever struggled with nested loops or found yourself wishing for cleaner ways to exit or skip iterations in higher-order functions, this feature is here to save the day.

In this blog, we’ll dive deep into what this feature is, why it matters, and how you can use it effectively in your Kotlin projects.

What Are Non-Local break and continue?

When working with higher-order functions like forEach, you might have noticed a limitation: there was no direct way to use break or continue. You had to rely on awkward workarounds, like adding return statements or using labeled loops.

With Kotlin 2.1, non-local break and continue allow you to:

  • Exit a loop (break)

  • Skip an iteration (continue)
    …directly from a higher-order function, just as you would in a regular loop!

This feature makes your code cleaner, more expressive, and easier to maintain.

Before Kotlin 2.1: The Android Struggle

Let’s say you’re iterating over a list of strings to filter valid user inputs:

kotlin
val inputs = listOf("valid_input", "invalid", "valid_input_2", "stop_here")

inputs.forEach { input ->
    if (input == "invalid") return@forEach  // Skip invalid inputs
    if (input == "stop_here") return  // Exit the loop
    Log.d("InputProcessing", "Processing: $input")
}
Log.d("InputProcessing", "Done!")

Here, return@forEach skips invalid inputs, but to break the loop entirely, you need workarounds like returning from the enclosing function. This can make the code harder to read and maintain.

After Kotlin 2.1: Clean and Intuitive

With non-local break and continue, Android developers can now write clear and concise code:

kotlin
val inputs = listOf("valid_input", "invalid", "valid_input_2", "stop_here")

inputs.forEach { input ->
    if (input == "invalid") continue  // Skip invalid inputs
    if (input == "stop_here") break  // Exit the loop
    Log.d("InputProcessing", "Processing: $input")
}
Log.d("InputProcessing", "Done!")

Output

javascript
D/InputProcessing: Processing: valid_input  
D/InputProcessing: Processing: valid_input_2  
D/InputProcessing: Done!

How It Works

Non-Local continue

You can use continue inside higher-order functions to skip the current iteration of the loop:

kotlin
val words = listOf("apple", "banana", "cherry", "date")

words.forEach { word ->
    if (word.startsWith("b")) continue
    println(word)
}

Output

javascript
apple  
cherry  
date

Non-Local break

You can use break to exit the loop entirely, even when using forEach:

kotlin
val words = listOf("apple", "banana", "cherry", "date")

words.forEach { word ->
    if (word.startsWith("c")) break
    println(word)
}

Output

javascript
apple  
banana

Where Can You Use It?

Non-local break and continue work seamlessly in Kotlin 2.1 in all inline higher-order functions. This includes functions like:

  • forEach

  • map

  • filter

However, they cannot be used in non-inline functions, as these do not support the required inlining for non-local control flow.

Examples in Action

Let’s explore some practical use cases:

Example 1: Processing Files

Suppose you’re reading a list of filenames and want to stop at the first invalid file:

kotlin
val files = listOf("file1.txt", "file2.txt", "invalid_file", "file3.txt")

files.forEach { file ->
    if (file.contains("invalid")) break
    println("Processing $file")
}

Output

javascript
Processing file1.txt  
Processing file2.txt

Example 2: Skipping Specific Items

You’re iterating over a list of items, but you want to skip items that match a certain condition:

kotlin
val numbers = listOf(10, 20, 30, 40, 50)

numbers.forEach { number ->
    if (number % 20 == 0) continue
    println(number)
}

Output

javascript
10  
30  
50

Example 3: Breaking Out of a Nested Loop

Non-local break can be a lifesaver when working with nested loops:

kotlin
val matrix = listOf(
    listOf(1, 2, 3),
    listOf(4, 5, 6),
    listOf(7, 8, 9)
)

matrix.forEach { row ->
    row.forEach { value ->
        if (value == 5) break
        println(value)
    }
    println("Finished row")  // This won't print for rows after the break
}

Output

javascript
1  
2  
3  
4  
Finished row

Conclusion

Kotlin 2.1’s non-local break and continue simplify working with loops inside higher-order functions. Whether you’re iterating over collections or processing data, this feature makes your code more concise, intuitive, and readable.

If you haven’t already upgraded to Kotlin 2.1, now is the perfect time to do so and start leveraging these improvements.


Akshay Nandwana
Founder AndroidEngineers

You can connect with me on:


Book 1:1 Session here
Click Here

Join our upcoming classes
https://www.androidengineers.in/courses

Share This Article
Stay Updated

Get the latest Android development articles delivered to your inbox.