forEach 中 如何退出循环?
上两周本人去面试的时候被问了个问题,就是 forEach 中如何退出循环?我的回答是采用 return 标签的方式,为什么我会这么回答?因为我压根就没有试过在 forEach 中退出循环,平时大多数情况都是使用的 for 循环,使用 break 和 continue 退出循环,今天顺便就记录下这个问题
错误写法
我们来看下下面的代码
fun main() {
val intList = listOf(1, 2, 3, 4, 5)
intList.forEach {
if (it == 3) return@forEach
println(it)
}
println("Foreach end")
}
正常来说,我们都是以为 return@forEach 已经跳出了循环,并且继续执行 println("Foreach end")
我们来看下输出
1
2
4
5
continueForeach end
可以看到,这个 return@forEach 在这里相当于 continue,而不是我们想要的 break
为什么会这样?
我们看下 forEach 是如何实现的
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}
高阶内联函数,for 循环遍历。如果对内联函数感兴趣可以康康我的这篇文章 Kotlin inline内联函数
所以我们在 lambda 中使用 return@forEach 会终止 当前这一次 lambda 的执行,并且循环执行下一次 lambda
@forEach 是 forEach 函数的隐式标签,当然你也可以这样,给 forEach 添加一个标签
fun main() {
val intList = listOf(1, 2, 3, 4, 5)
intList.forEach label@{
if (it == 3) return@label
println(it)
}
println("Foreach end")
}
forEach 中的 break
然后当我们头脑发热的时候,又尝试了下面的方法
fun main() {
val intList = listOf(1, 2, 3, 4, 5)
intList.forEach{
if (it == 3) return
println(it)
}
println("Foreach end")
}
来看下输出
1
2
为什么只输出了1、2, 最后的 Foreach end 却没输出?
因为这是内联函数啊,它会将代码拷贝到调用处,这里的 return 会终止 main 函数,官方把这种返回叫做 非局部返回,并且只有在内联函数的 lambda 内部才可以 return ,非内联函数直接就提示错误啦
那么如何实现 break ?
可以在 forEach 外部在套一层 lambda 表达式,例如这样
fun main() {
val intList = listOf(1, 2, 3, 4, 5)
run {
intList.forEach{
if (it == 3) return@run
println(it)
}
}
println("Foreach end")
}
当然你也可以 使用 let, apply 等扩展函数
参考文档
有兴趣的可以看下 官方文档
文章讨论了在Kotlin中使用forEach循环时如何退出的问题。通常,`return@forEach`实际上相当于`continue`,不会终止整个循环。由于forEach是内联函数,使用`return`会终止外层函数(如`main`)。要实现类似`break`的效果,可以使用`run`、`let`或`apply`等扩展函数,在其内部的lambda表达式中配合`return@run`来中断forEach循环。
1609





