详解Kotlin:forEach也能break和continue

作者:lqh 时间:2022-05-03 01:24:10 

详解Kotlin:forEach也能break和continue

这样的问题。也就是说,他们想用forEach而不是for循环,因为这很fp,很洋气(我也喜欢),

但是他们又想使用break和continue,也就是普通的流程控制语句中的控制语句。

这很不fp,因为原本有filter是用于完成这个工作的,还有flapMap。BennyHuo在他发的文章里面也说的是这种方法。

filter很fp,但是会导致两次遍历,这样的话给人一股效率很低的赶脚。而Java8的Stream API就只会遍历一次,
而且很fp。但是它会有lambda对象的产生而且实现超复杂(我没看过,不清楚),而Kotlin的集合框架可是能inline掉lambda的,

少产生了多少对象啊,怎么能和辣鸡Java同流合污呢?

有人提到使用label return,比如:


fun main(ags: Array<String>) {
(0..100).forEach {
 if (50 <= it) return@forEach
 println(it)
}
}

但是他做了实验之后发现这玩意只能相当于continue,也就是说你只能跳出当前循环,然后还是会继续下一轮。

讲道理这个你仔细想想就可以发现。为了搞清楚其中的道理,我们自己实现一个forEach。


fun Pair<Int, Int>.forEach(block: (Int) -> Unit) {
for (i in first..second) block.invoke(i)
}

然后调用一下:


Pair(1, 100).forEach(::println)

没毛病老铁。

然后你会发现,你在函数体内对block产生了(second - first)次调用,不论你怎么return,都只会跳出这个block,
它并不影响你之后继续调用这个block,也就是说这个for循环不受block行为的影响。

看起来无解了,那怎么办呢?

那么就让我来拯救你们吧。


fun main(ags: Array<String>) {
run outside@ {
 (0..20).forEach inside@ {
  if (10 <= it) return@outside
  println(it)
 }
}
}

编译之后运行结果:


0
1
2
3
4
5
6
7
8
9
Process finished with exit code 0

呐,跳出去了。

把label的名字起的清真一点,就是这样:


run breaking@ {
(0..20).forEach continuing@ {
 if (10 <= it) return@breaking
 println(it)
}
}

上面这是break,运行结果就上面那样。

下面这是continue,运行结果就是continue的效果。为了让效果表现的明显,我把println复制了一下,
分别在if前后,这样可以很清楚地看到效果。


run breaking@ {
(0..20).forEach continuing@ {
 print(it)
 if (10 <= it) return@continuing
 println(it)
}
}

运行一下:


00
11
22
33
44
55
66
77
88
99
1011121314151617181920
Process finished with exit code 0

而且只进行了一次迭代,非常清真,效率看起来也比较高。

如何证明只有一次迭代?我使用jd-gui逆向了刚才的代码,结果:


public final class _5Kt
{
public static final void main(@NotNull String[] args)
{
 Intrinsics.checkParameterIsNotNull(args, "args");
 int $i$a$1$run;
 Iterable $receiver$iv = (Iterable)new IntRange(0, 20);
 int $i$f$forEach;
 for (Iterator localIterator = $receiver$iv.iterator(); localIterator.hasNext();)
 {
  int element$iv = ((IntIterator)localIterator).nextInt();int it = element$iv;
  int $i$a$1$forEach;
  System.out.print(it);
  if (10 <= it) {
   break;
  }
  System.out.println(it);
 }
}
}

确实只有一次,而且jd-gui直接把我的行为反编译为break了。服不服?

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

来源:http://www.kotliner.cn/2017/04/25/KotlinForEachBreakContinue/

标签:Kotlin,forEach
0
投稿

猜你喜欢

  • SpringBoot响应处理之以Json数据返回的实现方法

    2023-12-21 12:21:47
  • java中transient关键字用法分析

    2022-01-22 04:27:05
  • SpringBoot实现接口数据的加解密功能

    2023-06-30 00:11:01
  • 关于java 图形验证码的解决方法

    2023-08-09 15:21:19
  • spring mvc实现文件上传并携带其他参数的示例

    2023-11-20 11:54:06
  • MyBatis配置的应用与对比jdbc的优势

    2023-08-27 07:03:47
  • java 如何计算同比增长工具类

    2023-11-09 08:50:35
  • c语言动态数组示例

    2023-11-02 22:56:44
  • 解决grails服务端口冲突的办法(grails修改端口号)

    2023-09-12 01:00:03
  • Java WebService 简单实例(附实例代码)

    2023-01-25 07:52:18
  • linux(center OS7)安装JDK、tomcat、mysql 搭建java web项目运行环境

    2022-07-04 07:02:37
  • SpringBoot持久化层操作支持技巧

    2023-11-24 06:40:32
  • Java中避免过多if-else的几种方法

    2023-11-28 13:07:09
  • Kafka 日志存储实现过程

    2021-11-01 05:04:00
  • Java二维数组简单定义与使用方法示例

    2022-01-28 08:31:37
  • java实现单机版五子棋

    2022-12-20 20:15:07
  • Java在web页面上的编码解码处理及中文URL乱码解决

    2023-08-25 11:10:19
  • android6.0权限动态申请框架permissiondispatcher的方法

    2023-07-31 10:51:57
  • Java 是如何利用接口避免函数回调的方法

    2023-11-11 10:14:00
  • java实现学生信息管理系统

    2023-11-11 08:22:35
  • asp之家 软件编程 m.aspxhome.com