Kotlin | 在for、forEach循环中正确的使用break、continue

文章目录

Kotlin 有三种结构化跳转表达式:

  • return :默认从最直接包围它的函数或者匿名函数返回。
  • break:终止最直接包围它的循环。
  • continue:继续下一次最直接包围它的循环。

for循环中使用break、continue

kotlin 复制代码
fun forControl() {
    for (i in 1..5) {
        if (i == 3) break //1 这里分别使用break continue return
        println("i: $i")
    }
    println("循环外继续执行")
}

1处分别使用break、continue、return 替换,执行结果如下:

kotlin 复制代码
//break 
i: 1
i: 2
循环外继续执行

//continue
i: 1
i: 2
i: 4
i: 5
循环外继续执行

//return
i: 1
i: 2

嗯,跟Java中的使用姿势是一样的,继续往下看。

Label标签

在 Kotlin 中任何表达式都可以用标签(label)来标记。 标签的格式为标识符后跟 @ 符号,例如:abc@、loop@都是有效的标签。 要为一个表达式加标签,我们只要在其前加标签即可。示例:

kotlin 复制代码
loop@ for (i in 1..5){
      //...
      }

这里在嵌套for循环中使用Label,可以控制break及continue的范围:

kotlin 复制代码
fun forNestedControl() {
   loop@ for (i in 1..2) {
          println("i: $i")
          for (j in 1..5) {
              if (j == 3) break@loop //break continue
              println("j: $j")
          }
      }
}

执行结果:

kotlin 复制代码
//break
i: 1
j: 1
j: 2
循环外继续执行

//continue
i: 1
j: 1
j: 2

i: 2
j: 1
j: 2
循环外继续执行

注意不能在上述代码中使用return@loop,因为目标标签表示的不是函数,错误信息如下:

Target label does not denote a function

结论:标签限制的 break 跳转到刚好位于该标签指定的循环后面的执行点。 continue 继续标签指定的循环的下一次迭代

forEach中如何退出循环

在forEach中并不能直接使用break、continue:

可以看到直接报错了,错误信息也很明确:break 和 continue 只允许在循环中使用 ,而这里是forEach的闭包,所以并不能直接使用break 和 continue。那么如何在forEach中分别模拟出break、continue的效果呢?通过Label即可实现,如:

kotlin 复制代码
fun forEachControl() {
    listOf(1, 2, 3, 4, 5).forEach forEach@{
        if (it == 3) return@forEach
        println("it:$it")
    }
    println("循环外继续执行")
}

return 只会从 lambda 表达式中返回。通常情况下使用隐式标签更方便(Label 标签与接受该 lambda 的函数同名即可使用隐式标签),简化之后:

kotlin 复制代码
fun forEachControl() {
    listOf(1, 2, 3, 4, 5).forEach{
        if (it == 3) return@forEach
        println("it:$it")
    }
    println("循环外继续执行")
}

代码执行结果:

kotlin 复制代码
it:1
it:2
it:4
it:5
循环外继续执行

可以看到return@forEach相当于表达式里面的continue了。嗯哼?为什么不是break的效果呢?明明已经return@forEach了呀,其实这是Kotlin闭包带来的副作用,看下forEach的源码:

kotlin 复制代码
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
    //注意看下面这行代码的逻辑
    for (element in this) action(element)
}

action闭包作为参数传入的,所以在forEach中return@forEach只能停止当前闭包的逻辑,后面的循环并不会受影响,会继续后面的循环。那么如何在forEach中模拟break的效果呢?只要把声明Label放到forEach外面即可以了:

kotlin 复制代码
fun forEachControl() {
    run loop@{
       listOf(1, 2, 3, 4, 5).forEach {
          if (it == 3) return@loop
          println("it:$it")
        }
          println("循环外继续执行")
        }
    }

执行结果:

kotlin 复制代码
it:1
it:2

资料

【1】Kotlin返回和跳转:https://www.kotlincn.net/docs/reference/returns.html

相关推荐
Kapaseker5 小时前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
Kapaseker1 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
A0微声z3 天前
Kotlin Multiplatform (KMP) 中使用 Protobuf
kotlin
alexhilton4 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
lhDream4 天前
Kotlin 开发者必看!JetBrains 开源 LLM 框架 Koog 快速上手指南(含示例)
kotlin
RdoZam4 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
Kapaseker4 天前
研究表明,开发者对Kotlin集合的了解不到 20%
android·kotlin
糖猫猫cc5 天前
Kite:两种方式实现动态表名
java·kotlin·orm·kite
如此风景5 天前
kotlin协程学习小计
android·kotlin
Kapaseker5 天前
你搞得懂这 15 个 Android 架构问题吗
android·kotlin