Kotlin | 在 for、forEach 循环中正确使用 break、continue
本文已同步发表于我的微信公众号,微信搜索
代码说
即可关注,欢迎与我沟通交流。
Kotlin 有三种结构化跳转表达式:
- return:默认从最直接包围它的函数或者匿名函数返回。
- break:终止最直接包围它的循环。
- continue:继续下一次最直接包围它的循环。
for循环中使用break、continue
for (i in 1..5) {
if (i == 3) break //1 这里分别使用break continue return
println("i: $i")
}
println("循环外继续执行")
1处分别使用break、continue、return 替换,执行结果如下:
//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@都是有效的标签。 要为一个表达式加标签,我们只要在其前加标签即可。示例:
loop@ for (i in 1..5){
//...
}
这里在嵌套for循环中使用Label,可以控制break及continue的范围:
loop@ for (i in 1..2) {
println("i: $i")
for (j in 1..5) {
if (j == 3) break@loop //break continue
println("j: $j")
}
}
println("循环外继续执行")
执行结果:
//break
i: 1
j: 1
j: 2
循环外继续执行
//continue
i: 1
j: 1
j: 2
i: 2
j: 1
j: 2
循环外继续执行
结论:Label标签限制的 break 跳转到刚好位于该标签指定的循环后面的执行点。 continue 继续标签指定的循环的下一次迭代。
注意不能在上述代码中使用return@loop
,因为目标标签表示的不是函数,错误信息如下:
Target label does not denote a function
forEach中模拟break、continue
在forEach中并不能直接使用break、continue:
可以看到直接报错了,错误信息也很明确:break 和 continue 只允许在循环中使用,而这里是forEach的闭包,所以并不能直接使用break 和 continue
。那么如何在forEach中分别模拟出break、continue的效果呢?通过Label即可实现,如:
fun forEachControl() {
listOf(1, 2, 3, 4, 5).forEach forEach@{
if (it == 3) return@forEach
println("it:$it")
}
println("循环外继续执行")
}
return 只会从 lambda 表达式中返回。通常情况下使用隐式标签更方便(Label 标签与接受该 lambda 的函数同名即可使用隐式标签
),简化之后:
fun forEachControl() {
listOf(1, 2, 3, 4, 5).forEach{
if (it == 3) return@forEach
println("it:$it")
}
println("循环外继续执行")
}
代码执行结果:
it:1
it:2
it:4
it:5
循环外继续执行
可以看到return@forEach
相当于表达式里面的continue了。嗯哼?为什么不是break的效果呢?明明已经return@forEach
了呀,其实这是Kotlin闭包带来的副作用,看下forEach的源码:
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外面即可以了:
fun forEachControl() {
run loop@{//1
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop//2
println("it:$it")
}
println("循环外继续执行")
}
}
执行结果:
it:1
it:2
可以看到1处的Label
标签放到了forEach
的外层了,那么当执行2处的return@loop
时会直接跳出forEach
循环,进而实现了break
功能。
资料
【1】Kotlin返回和跳转:https://www.kotlincn.net/docs/reference/returns.html
欢迎扫描下方二维码
或搜索微信公众号 代码说
, 关注我的微信公众号查看最新文章~
上一篇: python | %d、%2d、%-2d、%.2d、%02d 之间的差值
下一篇: SpringBoot 核心功能 - ApplicationRunner && CommandLineRunner 的使用
推荐阅读
-
vue2 中的双向绑定是什么,为什么要针对 vue3 进行优化?
-
如何在 php 代码中实现万年历
-
如何在 excel 中自动生成敏感性分析图表
-
LeetCode 面试经典 150 题 28.找出字符串中第一个匹配项的下标
-
[备忘录] C 中的 nan 和 inf
-
C 语言中的循环圈
-
ARP 协议有什么作用--ARP(AddressResolutionProtocol,地址解析协议)地址解析协议用于将计算机的网络地址(32 位 IP 地址)转换为物理地址(48 位 MAC 地址)[RFC826]。ARP 协议属于链路层协议,在以太网网络中,数据帧从一台主机传送到网络中的另一台主机时,是根据 48 位以太网地址(硬件地址)来确定接口的,而不是根据 32 位 IP 地址。内核(如驱动程序)必须知道目的地的硬件地址,才能发送数据。当然,点对点连接不需要 ARP 协议。 ARP 协议示例
-
远程登录使用什么协议
-
PHP 使用 IMAP 协议接收外部邮件
-
[云本地网络] 模拟运行!在两分钟内了解 BGP