Kotlin Loop Control
For Loop
The for loop can iterate through any object that provides an iterator. The syntax is as follows:
for (item in collection) print(item)
The loop body can be a code block:
for (item: Int in ints) {
// ……
}
As mentioned above, for can iterate through any object that provides an iterator.
If you want to traverse an array or a list by index, you can do this:
for (i in array.indices) {
print(array[i])
}
Note that this "iteration over a range" compiles to an optimized implementation without creating extra objects.
Alternatively, you can use the library function withIndex:
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
Example
Iterating over a collection:
fun main(args: Array<String>) {
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println(item)
}
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
}
Output result:
apple banana kiwi item at 0 is apple item at 1 is banana item at 2 is kiwi
while and do...while Loops
while is the most basic loop; its structure is:
while( 布尔表达式 ) {
//循环内容
}
do...while Loop For the while statement, if the condition is not met, the loop cannot be entered. But sometimes we need to execute at least once even if the condition is not met.
The do...while loop is similar to the while loop, except that the do...while loop is executed at least once.
do {
//代码语句
}while(布尔表达式);
Example
fun main(args: Array<String>) {
println("----while 使用-----")
var x = 5
while (x > 0) {
println( x--)
}
println("----do...while 使用-----")
var y = 5
do {
println(y--)
} while(y>0)
}
Output result:
----while 使用----- 5 4 3 2 1 ----do...while 使用----- 5 4 3 2 1
Returns and Jumps
Kotlin has three structured jump expressions:
- returnBy default, returns from the function or anonymous function that most directly surrounds it.
- breakTerminates the loop that most directly surrounds it.
- continueContinues to the next iteration of the loop that most directly surrounds it.
In loops, Kotlin supports the traditional break and continue operators.
fun main(args: Array<String>) {
for (i in 1..10) {
if (i==3) continue // i 为 3 时跳过当前循环,继续下一次循环
println(i)
if (i>5) break // i 为 6 时 跳出循环
}
}
Output result:
1 2 4 5 6
Break and Continue Labels
In Kotlin, any expression can be marked with a label. The format of a label is an identifier followed by the @ symbol, for example: abc@ and fooBar@ are valid labels. To label an expression, we simply put the label in front of it.
loop@ for (i in 1..100) {
// ……
}
Now, we can use labels to qualify break or continue:
loop@ for (i in 1..100) {
for (j in 1..100) {
if (……) break@loop
}
}
A labeled break jumps to the execution point just after the loop specified by the label. A labeled continue proceeds to the next iteration of the loop specified by the label.
Return at Labels
Kotlin has function literals, local functions, and object expressions. Therefore, Kotlin functions can be nested. A labeled return allows us to return from an outer function. One of the most important uses is returning from a lambda expression. Recall when we write:
fun foo() {
ints.forEach {
if (it == 0) return
print(it)
}
}
This return expression returns from the function that directly surrounds it, i.e., foo. (Note that this kind of non-local return is only supported for lambda expressions passed to inline functions.) If we need to return from a lambda expression, we must label it and use that label to qualify the return.
fun foo() {
ints.forEach lit@ {
if (it == 0) return@lit
print(it)
}
}
Now, it will only return from the lambda expression. Usually it is more convenient to use an implicit label. This label has the same name as the function that accepts the lambda.
fun foo() {
ints.forEach {
if (it == 0) return@forEach
print(it)
}
}
Alternatively, we can replace the lambda expression with an anonymous function. A return statement inside an anonymous function will return from the anonymous function itself.
fun foo() {
ints.forEach(fun(value: Int) {
if (value == 0) return
print(value)
})
}
When a value is to be returned, the parser prefers the label-qualified return, i.e.,
return@a 1
This means "return 1 from the label @a", not "return a label-annotated expression (@a 1)".
Other Extensions