Kotlin中如何退出forEach
在 Kotlin 中,forEach
是一个高阶函数,它在遍历集合时会对集合中的每一个元素执行给定的 lambda 表达式。若要在 forEach
中退出循环, return
会返回到外层函数,而不是终止循环。因此,使用 return@forEach
不能达到预期的效果。
合理的做法是使用带标签的 return
或者是使用其他循环结构,如 for
循环。在 forEach
中你可以使用自定义的标签配合 return
,以退出循环。
例如:
1、 使用 for
循环:
val map = hashMapOf("one" to 1, "two" to 2, "three" to 3)
for ((key, value) in map) {
if (key == "two") {
break // 退出循环
}
println("$key -> $value")
}
2、 使用标签和 forEach
:
val map = hashMapOf("one" to 1, "two" to 2, "three" to 3)
run loop@{
map.forEach { (key, value) ->
if (key == "two") {
return@loop // 退出循环
}
println("$key -> $value")
}
}
在这个例子中,run loop@{}
的形式创建了一个标签为 loop
的作用域,然后 return@loop
的作用是退出这个作用域,从而实现直接退出遍历。
其他需要注意的情况
在 Kotlin 中,标签(label)和 return
、break
、continue
搭配使用的情况,与 Java 有一些区别。除了前面提到的在 forEach
中退出循环的情况,以下是一些其他值得注意的情况:
1. 退出嵌套循环中的控制流
在嵌套循环中,你可以使用标签来方便地控制外层循环的中断或继续,这是 Java 中没有的直接用法。
代码语言:javascript复制// Java 中的控制流
outer: for (int i = 0; i < 10; i ) {
for (int j = 0; j < 10; j ) {
if (j == 5) break outer; // 退出外层循环
}
}
// Kotlin 中的控制流
outer@ for (i in 0 until 10) {
for (j in 0 until 10) {
if (j == 5) break@outer // 退出外层循环
}
}
2. 带标签的 return
退出闭包操作
在高阶函数中,例如 forEach
、map
、filter
等闭包操作中,如果你需要提前退出,可以使用带标签的 return
。
在 Kotlin Standard Library 中,如果想中断 forEach
或其他 lambda 表达式,直接 return
会导致外层函数返回,因此需要使用标签。
listOf(1, 2, 3, 4, 5).forEach loop@{
if (it == 3) return@loop // 退出当前的 lambda 表达式
println(it)
}
println("Done with forEach")
3. run
, with
, apply
, also
等标准库函数
这类函数也经常用标签配合返回的方式提前中断执行,其中 return
是返回到调用这些函数的上下文,而 return@label
是退出当前作用域。
run myRun@{
val myList = listOf(1, 2, 3, 4)
myList.forEach {
if (it == 3) return@myRun // 退出 run 块
}
println("This will not be printed if '3' is found in the list.")
}
println("Outside the run block.")
4. inline
函数与非局部返回
当你在一个 inline
函数内使用 return
时,通常是非局部返回,即返回到调用此 inline
函数的外层函数。
inline fun myInlineFunction(block: () -> Unit) {
block()
println("After block") // 这一行只有在 block 里没有非局部返回时才会执行
}
fun main() {
myInlineFunction {
println("Before return")
return // 非局部返回到 main 函数
}
println("This will not be printed")
}
//上面只会打印:Before return
通过 inline
和非局部返回,你能够在高阶函数中实现类似早期的 goto
的效果,但是更安全、更易懂。
5. 带接收者的 lambda 表达式
在带接收者的 lambda 表达式中,比如适用 with
、apply
、let
、run
这样的标准库函数,配合标签时可能运行逻辑会发生变化:
val myStringBuilder = StringBuilder().apply {
append("Hello, ")
append("world")
return@apply // 这将返回 StringBuilder 实例
}
总结:Kotlin 中标签和控制流结合的使用可以帮助开发者更灵活地操控代码的执行流,尤其是在高阶函数和嵌套结构中显现出强大的优势。了解并充分利用这些特性,可以使代码更加简洁易懂,并减少错误。