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

2023-09-18 23:54:18

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

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

for循环中使用break、continue

fun forControl() {
    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的范围:

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")
          }
      }
}

执行结果:

//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错误使用
可以看到直接报错了,错误信息也很明确: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@{
       listOf(1, 2, 3, 4, 5).forEach {
          if (it == 3) return@loop
          println("it:$it")
        }
          println("循环外继续执行")
        }
    }

执行结果:

it:1
it:2

资料

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

更多推荐

《DevOps实践指南》- 读书笔记(九)

DevOps实践指南25.附录附录1DevOps的大融合精益运动敏捷运动Velocity大会运动敏捷基础设施运动持续交付运动丰田套路运动精益创业运动精益用户体验运动RuggedComputing运动附录2约束理论和核心的长期冲突附录3恶性循环列表附录4交接和队列的危害附录5工业安全误区附录6丰田安灯绳附录7软件包产品附

QT之时间相关的函数

QT之时间相关的函数1)QDateTime:QDateTime是一个表示日期和时间的类,可以表示从公元1年1月1日至今的日期和时间。可以使用QDateTime类的各种方法来创建、比较和格式化日期和时间。例如,QDateTime::currentDateTime()可以获取当前日期和时间。2)QDate:QDate是一个

排查disabled问题之谷歌新版本特性

问题复现最近我突然接手一个后台的bug,这个后台很久没有迭代更新了,我也不熟悉业务,所以只能看一下源码,问题很快就复现,测试的修复操作也很正确,就是因为渲染的input标签中存在disabled='disabled’属性导致的。不过很奇怪的是,我问之前是正常的吗?这部分代码已经很久没有改动过了但是测试和运营那边的人员都

Gavin Wood 演讲全文:建设更具韧性以应变化的 Polkadot

我们非常激动能邀请到GavinWood博士来现场分享关于Polkadot的近况以及最新的进展,带来他对于《加密项目应该怎样应对当今世界的变化》的演讲分享。🚩点击视频链接观看演讲实录:https://www.youtube.com/watch?v=Yw3mQNJ5UJQ&t=1048s以下是演讲回顾:世界正改变,看到W

文举论金:黄金原油全面走势分析策略指导。

市场没有绝对,涨跌没有定势,所以,对市场行情的涨跌平衡判断就是你的制胜法宝。欲望!有句意大利谚语:让金钱成为我们忠心耿耿的仆人,否则,它就会成为一个专横跋扈的主人。空头,多头都能赚钱,唯有贪心不能赚。是你掌控欲望还是欲望掌控你?古人云:不积硅步无以至千里,不积小流无以成江海。希望这句话成为我们之间的共勉。自知!人贵自知

【HTTPS】运营商劫持、中间人攻击 与 加密

运营商劫持、中间人攻击与加密一.HTTPS是什么二.臭名昭著的"运营商劫持"三.加密1."加密"是什么2.HTTPS的工作过程3.对称加密4.非对称加密四.中间人攻击五.证书证书校验证书篡改六.完整流程一.HTTPS是什么HTTPS也是一个应用层协议.是在HTTP协议的基础上引入了一个加密层.HTTP协议内容都是按照文

C++基础第一章:头文件,输入符,输出符,控制符,换行符

第一章C++基础头文件1:头文件1.0:头文件:其中有带h和没有带h后缀的,带h后缀的是老版本的编译器,没带是新版本的编译器。#include<limits.h>#最大最小要导入这个#include<ctype.h>#字符处理函数功能#define_CRT_SECURE_NO_WARNINGS#include<iost

.NET中使用Quartz

Quartz是一个流行的开源任务调度库,它提供了强大的任务调度功能,可以方便地与.NET应用程序集成。Quartz.NET是Quartz的.NET版本,它是为.NET框架编写的,并提供了与.NET应用程序的集成。它支持各种调度策略,包括定时、间隔、日历等,可以灵活地配置和管理任务。Quartz.NET具有以下特点:开源

CodeTON Round 6 (Div 1 + Div 2, Rated, Prizes!)

CodeTONRound6(Div.1+Div.2,Rated,Prizes!)(A-E)CodeTONRound6(Div.1+Div.2,Rated,Prizes!)A.MEXanizedArray(分类讨论)可以发现当n<k或者k>x+1的时候无法构成,其余的时候贪心的用x最大化贡献即可,注意特判k==x的情况。

Go业务开发常用关注点

本文对实际开发场景中面对高频的场景,总结出来的一些处理方案,希望能对业务开发的同学提供帮助!结构体转换实际开发中会面对一个相似的数据结构,由于引用不同的包,需要开发转换到对应的结构上,本质上这些数据结构是一致的,但是所在包不同所以不能直接赋值。常规的方案大致分为下面几种:直接转换struct这种适合结构完全一致的情况,

墨天轮专访星环科技刘熙:“向量热”背后的冷思考,Hippo如何打造“先发”优势?

导读:深耕技术研发数十载,坚持自主可控发展路。星环科技一路砥砺前行、坚持创新为先,建设了全面的产品矩阵,并于2022年作为首个独立基础软件产品公司成功上市。星环科技在今年的向星力•未来技术大会上发布了分布式向量数据库TranswarpHippo以及两款领域大模型“无涯”和“求索”。关于星环科技在向量数据库领域的建树和背

热文推荐