Kotlin中如何优雅地退出循环

在 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)和 returnbreakcontinue 搭配使用的情况,与 Java 有一些区别。除了前面提到的在 forEach 中退出循环的情况,以下是一些其他值得注意的情况:

1. 退出嵌套循环中的控制流

在嵌套循环中,你可以使用标签来方便地控制外层循环的中断或继续,这是 Java 中没有的直接用法。

// 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退出闭包操作

在高阶函数中,例如 forEachmapfilter 等闭包操作中,如果你需要提前退出,可以使用带标签的 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. runwithapplyalso 等标准库函数

这类函数也经常用标签配合返回的方式提前中断执行,其中 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 表达式中,比如适用 withapplyletrun 这样的标准库函数,配合标签时可能运行逻辑会发生变化:

val myStringBuilder = StringBuilder().apply {
    append("Hello, ")
    append("world")
    return@apply // 这将返回 StringBuilder 实例
}

总结:Kotlin 中标签和控制流结合的使用可以帮助开发者更灵活地操控代码的执行流,尤其是在高阶函数和嵌套结构中显现出强大的优势。了解并充分利用这些特性,可以使代码更加简洁易懂,并减少错误。

转自:Android Kotlin中如何优雅地退出循环?

在otlin,for循环有两种形式。第一种形式是使用`in`关键字和区间来迭代元素。例如,`for (i in 1..5)`表示迭代从1到5的数字。第二种形式是使用`in`关键字和集合来迭代元素。例如,`for (item in list)`表示迭代集合`list`的每个元素。 Kotlin的for循环也支持跳出循环和继续循环的功能。我们可以使用`break`关键字来跳出当前循环,使用`continue`关键字来继续下一次循环。 请注意,Kotlin没有像Java那样的传统for循环,如果需要按索引迭代,可以使用`indices`属性或`withIndex()`函数与for循环结合使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Kotlin基础学习之循环和异常](https://download.csdn.net/download/weixin_38700430/12767633)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Kotlin循环](https://blog.csdn.net/zull_kos_mos/article/details/89670229)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值