Kotlin forEach 中 如何退出循环?

forEach 中 如何退出循环?

上两周本人去面试的时候被问了个问题,就是 forEach 中如何退出循环?我的回答是采用 return 标签的方式,为什么我会这么回答?因为我压根就没有试过在 forEach 中退出循环,平时大多数情况都是使用的 for 循环,使用 breakcontinue 退出循环,今天顺便就记录下这个问题

错误写法

我们来看下下面的代码

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

@forEachforEach 函数的隐式标签,当然你也可以这样,给 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")
}

当然你也可以 使用 letapply 等扩展函数

参考文档

有兴趣的可以看下 官方文档

你可能感兴趣的:(Kotlin日记,kotlin,android)