The Kotlin break continue statements are structural jump expressions that modify the normal flow of loop execution. While break terminates the loop entirely, continue skips the current iteration and moves to the next one. These statements work with all types of loops in Kotlin, including for loops, while loops, and do-while loops.
The Kotlin break statement immediately terminates the nearest enclosing loop when a specific condition is met. When the program encounters a break statement, it exits the loop and continues executing the code that follows the loop block.
The basic syntax for using break in different loop types:
// Using break in for loop
for (element in collection) {
if (condition) {
break
}
// Other code
}
// Using break in while loop
while (condition) {
if (testCondition) {
break
}
// Other code
}
// Using break in do-while loop
do {
if (testCondition) {
break
}
// Other code
} while (condition)
Here’s a practical example demonstrating how break works in a for loop:
fun searchInNumbers() {
val numbers = listOf(10, 25, 3, 40, 15, 8)
for (number in numbers) {
println("Checking number: $number")
if (number > 30) {
println("Found number greater than 30: $number")
break // Exit the loop immediately
}
}
println("Search completed")
}
In this example, the loop stops as soon as it finds a number greater than 30, demonstrating how break prevents unnecessary iterations.
The Kotlin continue statement skips the remaining code in the current iteration and jumps to the next iteration of the loop. Unlike break, continue doesn’t terminate the entire loop but simply bypasses the current cycle.
The continue statement follows this pattern in different loops:
// Using continue in for loop
for (element in collection) {
if (skipCondition) {
continue
}
// This code executes only if skipCondition is false
}
// Using continue in while loop
while (condition) {
if (skipCondition) {
continue
}
// Process elements
}
Let’s see how continue works in filtering operations:
fun processEvenNumbers() {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
var sum = 0
for (number in numbers) {
if (number % 2 != 0) {
continue // Skip odd numbers
}
sum += number
println("Added even number: $number, Current sum: $sum")
}
println("Final sum of even numbers: $sum")
}
This example demonstrates how continue helps process only specific elements while skipping others based on conditions.
Kotlin break continue statements become even more powerful when combined with labels. Labels allow you to control exactly which loop to break or continue, especially useful in nested loop scenarios.
A label in Kotlin consists of an identifier followed by the @ symbol. You can label any expression and reference it later with break or continue statements.
labelName@ for (element in collection) {
// Loop body
}
Here’s how labeled break works with nested loops:
fun demonstrateLabeledBreak() {
outerLoop@ for (i in 1..5) {
innerLoop@ for (j in 1..5) {
println("Processing: i=$i, j=$j")
if (i == 3 && j == 2) {
println("Breaking outer loop at i=3, j=2")
break@outerLoop // Breaks the outer loop
}
if (j == 4) {
println("Breaking inner loop at j=4")
break@innerLoop // Breaks only the inner loop
}
}
println("Completed inner loop for i=$i")
}
println("Program completed")
}
Labeled continue provides precise control over which loop iteration to skip:
fun demonstrateLabeledContinue() {
outerLoop@ for (i in 1..4) {
println("Starting outer loop iteration: $i")
innerLoop@ for (j in 1..4) {
if (i == 2 && j == 2) {
println("Skipping outer loop iteration at i=2, j=2")
continue@outerLoop // Skip to next outer loop iteration
}
if (j == 3) {
println("Skipping inner loop iteration at j=3")
continue@innerLoop // Skip to next inner loop iteration
}
println("Processing: i=$i, j=$j")
}
println("Completed inner loop for i=$i")
}
}
While loops often use break and continue for user input validation and processing:
fun userInputProcessor() {
var userInput: String?
var validInputCount = 0
while (validInputCount < 3) {
print("Enter a positive number (or 'quit' to exit): ")
userInput = readLine()
if (userInput == "quit") {
println("Exiting program...")
break // Exit the while loop
}
val number = userInput?.toIntOrNull()
if (number == null || number <= 0) {
println("Invalid input. Please try again.")
continue // Skip to next iteration
}
validInputCount++
println("Valid input #$validInputCount: $number")
}
if (validInputCount == 3) {
println("Successfully collected 3 valid inputs!")
}
}
Do-while loops guarantee at least one execution before checking conditions:
fun menuDrivenProgram() {
var choice: String?
do {
println("\n=== Menu ===")
println("1. Option A")
println("2. Option B")
println("3. Exit")
print("Enter your choice: ")
choice = readLine()
when (choice) {
"1" -> {
println("Executing Option A...")
// Some processing here
continue // Go back to menu
}
"2" -> {
println("Executing Option B...")
// Some processing here
continue // Go back to menu
}
"3" -> {
println("Goodbye!")
break // Exit the loop
}
else -> {
println("Invalid choice. Please try again.")
continue // Show menu again
}
}
} while (true)
}
Here’s a practical example for processing student grades:
data class Student(val name: String, val grade: Int, val isActive: Boolean)
fun processStudentGrades() {
val students = listOf(
Student("Alice", 85, true),
Student("Bob", 45, false),
Student("Charlie", 92, true),
Student("Diana", 78, true),
Student("Eve", 35, true),
Student("Frank", 88, false)
)
var totalGrades = 0
var activeStudentCount = 0
val passingGrade = 50
studentLoop@ for (student in students) {
// Skip inactive students
if (!student.isActive) {
println("Skipping inactive student: ${student.name}")
continue@studentLoop
}
// Stop if we find a failing active student
if (student.grade < passingGrade) {
println("Found failing student: ${student.name} with grade ${student.grade}")
println("Stopping grade calculation for review")
break@studentLoop
}
totalGrades += student.grade
activeStudentCount++
println("Added ${student.name}'s grade: ${student.grade}")
}
if (activeStudentCount > 0) {
val averageGrade = totalGrades.toDouble() / activeStudentCount
println("Average grade of processed active students: ${"%.2f".format(averageGrade)}")
}
}
fun processLogFiles() {
val logEntries = listOf(
"INFO: Application started",
"DEBUG: Loading configuration",
"ERROR: Database connection failed",
"WARN: Retrying connection",
"INFO: Connection restored",
"FATAL: Critical system failure",
"INFO: System recovering"
)
var errorCount = 0
val maxErrors = 2
logProcessing@ for ((index, entry) in logEntries.withIndex()) {
println("Processing log entry ${index + 1}: $entry")
// Skip debug entries
if (entry.startsWith("DEBUG")) {
println("Skipping debug entry")
continue@logProcessing
}
// Count errors
if (entry.startsWith("ERROR") || entry.startsWith("FATAL")) {
errorCount++
println("Error detected. Total errors: $errorCount")
// Stop processing if too many errors
if (errorCount >= maxErrors) {
println("Maximum error threshold reached. Stopping log processing.")
break@logProcessing
}
}
// Process other entries
if (entry.startsWith("INFO") || entry.startsWith("WARN")) {
println("Normal log entry processed")
}
}
println("Log processing completed. Total errors found: $errorCount")
}
While traditional break and continue don’t work with functional methods like forEach, Kotlin provides alternatives using labeled returns:
fun functionalContinueExample() {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
var sum = 0
numbers.forEach { number ->
if (number % 2 == 0) {
return@forEach // Simulates continue - skip even numbers
}
sum += number
println("Added odd number: $number")
}
println("Sum of odd numbers: $sum")
}
fun functionalBreakExample() {
val items = listOf("apple", "banana", "cherry", "date", "elderberry")
run breakLoop@ {
items.forEach { item ->
println("Processing: $item")
if (item.startsWith("d")) {
println("Found item starting with 'd': $item")
return@breakLoop // Simulates break
}
println("Processed: $item")
}
}
println("Processing completed")
}
Kotlin break continue statements work well with error handling patterns:
fun robustDataProcessor() {
val dataItems = listOf("123", "abc", "456", "def", "789", "", "101112")
var successfulItems = 0
var totalValue = 0
dataProcessing@ for ((index, item) in dataItems.withIndex()) {
println("Processing item ${index + 1}: '$item'")
try {
// Skip empty strings
if (item.isEmpty()) {
println("Skipping empty item")
continue@dataProcessing
}
val numericValue = item.toInt()
// Stop if we encounter a number that's too large
if (numericValue > 10000) {
println("Number too large: $numericValue. Stopping processing.")
break@dataProcessing
}
totalValue += numericValue
successfulItems++
println("Successfully processed: $numericValue")
} catch (e: NumberFormatException) {
println("Skipping non-numeric item: '$item'")
continue@dataProcessing
}
}
println("Processing summary:")
println("- Successfully processed items: $successfulItems")
println("- Total value: $totalValue")
if (successfulItems > 0) {
println("- Average value: ${totalValue.toDouble() / successfulItems}")
}
}
Here’s a comprehensive example that demonstrates all concepts covered:
// Import statements
import kotlin.random.Random
// Data classes
data class Product(val id: Int, val name: String, val price: Double, val inStock: Boolean)
data class Order(val productId: Int, val quantity: Int)
fun main() {
// Sample data
val products = listOf(
Product(1, "Laptop", 999.99, true),
Product(2, "Mouse", 25.50, false),
Product(3, "Keyboard", 79.99, true),
Product(4, "Monitor", 299.99, true),
Product(5, "Webcam", 89.99, false),
Product(6, "Speakers", 129.99, true)
)
val orders = listOf(
Order(1, 2),
Order(2, 1),
Order(3, 3),
Order(4, 1),
Order(5, 2),
Order(6, 1)
)
println("=== E-commerce Order Processing System ===\n")
// Process orders with break and continue
processOrders(products, orders)
println("\n=== Inventory Management ===\n")
// Inventory check with labeled loops
performInventoryCheck(products)
println("\n=== Price Analysis ===\n")
// Price analysis with functional approach
analyzePrices(products)
}
fun processOrders(products: List<Product>, orders: List<Order>) {
var totalRevenue = 0.0
var processedOrders = 0
val maxOrdersToProcess = 4
println("Processing customer orders...")
orderProcessing@ for ((orderIndex, order) in orders.withIndex()) {
println("\nProcessing order ${orderIndex + 1}: Product ID ${order.productId}, Quantity ${order.quantity}")
// Stop processing if we've reached the maximum
if (processedOrders >= maxOrdersToProcess) {
println("Reached maximum order processing limit ($maxOrdersToProcess)")
break@orderProcessing
}
// Find the product
val product = products.find { it.id == order.productId }
if (product == null) {
println("Product not found for ID ${order.productId}. Skipping order.")
continue@orderProcessing
}
// Check if product is in stock
if (!product.inStock) {
println("Product '${product.name}' is out of stock. Skipping order.")
continue@orderProcessing
}
// Process the order
val orderTotal = product.price * order.quantity
totalRevenue += orderTotal
processedOrders++
println("✓ Order processed successfully!")
println(" Product: ${product.name}")
println(" Unit Price: $${product.price}")
println(" Quantity: ${order.quantity}")
println(" Order Total: $${String.format("%.2f", orderTotal)}")
}
println("\n--- Order Processing Summary ---")
println("Total orders processed: $processedOrders")
println("Total revenue generated: $${String.format("%.2f", totalRevenue)}")
println("Average order value: $${String.format("%.2f", if (processedOrders > 0) totalRevenue / processedOrders else 0.0)}")
}
fun performInventoryCheck(products: List<Product>) {
val categories = listOf("Electronics", "Accessories", "Peripherals")
var categoriesChecked = 0
println("Starting comprehensive inventory check...")
categoryLoop@ for ((categoryIndex, category) in categories.withIndex()) {
println("\nChecking category: $category")
var categoryHasStock = false
productLoop@ for (product in products) {
// Simulate category assignment based on price ranges
val productCategory = when {
product.price > 500 -> "Electronics"
product.price > 50 -> "Peripherals"
else -> "Accessories"
}
// Skip products not in current category
if (productCategory != category) {
continue@productLoop
}
println(" Checking ${product.name}...")
// If we find any out-of-stock item in Electronics, stop checking this category
if (category == "Electronics" && !product.inStock) {
println(" ⚠️ Critical item out of stock in Electronics: ${product.name}")
println(" Stopping Electronics category check for immediate restocking")
break@productLoop
}
if (product.inStock) {
categoryHasStock = true
println(" ✓ ${product.name} - In Stock ($${product.price})")
} else {
println(" ✗ ${product.name} - Out of Stock ($${product.price})")
}
}
categoriesChecked++
if (categoryHasStock) {
println("✓ Category '$category' has items in stock")
} else {
println("⚠️ Category '$category' needs restocking")
}
// Simulate stopping after critical category if needed
if (category == "Electronics" && !categoryHasStock) {
println("Critical inventory issue detected. Stopping full inventory check.")
break@categoryLoop
}
}
println("\n--- Inventory Check Summary ---")
println("Categories checked: $categoriesChecked/${categories.size}")
}
fun analyzePrices(products: List<Product>) {
println("Analyzing product prices...")
var expensiveProductsCount = 0
val priceThreshold = 100.0
// Using functional approach with labeled returns
println("\nFinding expensive products (>${priceThreshold}):")
run analysis@ {
products.forEach { product ->
if (!product.inStock) {
return@forEach // Skip out-of-stock items (simulates continue)
}
if (product.price > priceThreshold) {
expensiveProductsCount++
println(" ${product.name}: $${product.price}")
// Stop after finding 3 expensive products
if (expensiveProductsCount >= 3) {
println(" Found enough expensive products for analysis")
return@analysis // Simulates break
}
}
}
}
println("\nPrice analysis completed.")
println("Expensive products found: $expensiveProductsCount")
}
When you run this complete program, you’ll see output like this:
=== E-commerce Order Processing System ===
Processing customer orders...
Processing order 1: Product ID 1, Quantity 2
✓ Order processed successfully!
Product: Laptop
Unit Price: $999.99
Quantity: 2
Order Total: $1999.98
Processing order 2: Product ID 2, Quantity 1
Product 'Mouse' is out of stock. Skipping order.
Processing order 3: Product ID 3, Quantity 3
✓ Order processed successfully!
Product: Keyboard
Unit Price: $79.99
Quantity: 3
Order Total: $239.97
Processing order 4: Product ID 4, Quantity 1
✓ Order processed successfully!
Product: Monitor
Unit Price: $299.99
Quantity: 1
Order Total: $299.99
Processing order 5: Product ID 5, Quantity 2
Product 'Webcam' is out of stock. Skipping order.
Reached maximum order processing limit (4)
--- Order Processing Summary ---
Total orders processed: 3
Total revenue generated: $2539.94
Average order value: $846.65
=== Inventory Management ===
Starting comprehensive inventory check...
Checking category: Electronics
Checking Laptop...
✓ Laptop - In Stock ($999.99)
Checking Monitor...
✓ Monitor - In Stock ($299.99)
✓ Category 'Electronics' has items in stock
Checking category: Accessories
Checking Mouse...
✗ Mouse - Out of Stock ($25.5)
⚠️ Category 'Accessories' needs restocking
Checking category: Peripherals
Checking Keyboard...
✓ Keyboard - In Stock ($79.99)
Checking Webcam...
✗ Webcam - Out of Stock ($89.99)
Checking Speakers...
✓ Speakers - In Stock ($129.99)
✓ Category 'Peripherals' has items in stock
--- Inventory Check Summary ---
Categories checked: 3/3
=== Price Analysis ===
Analyzing product prices...
Finding expensive products (>100.0):
Laptop: $999.99
Monitor: $299.99
Speakers: $129.99
Found enough expensive products for analysis
Price analysis completed.
Expensive products found: 3
This comprehensive example demonstrates how Kotlin break continue statements work in real-world scenarios, combining basic usage, labeled control flow, functional programming approaches, and practical business logic. The code shows how these control statements help create efficient, readable, and maintainable applications.
The key takeaways from mastering Kotlin break continue statements include understanding when to use each statement, leveraging labels for complex nested loops, and knowing how to simulate similar behavior in functional programming contexts. These powerful tools will help you write more efficient Kotlin code for any application, whether you’re developing Android apps, server-side applications, or any other Kotlin project.