详解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/
猜你喜欢
- 程序的结构分类:顺序结构:按照写代码的顺序 一次执行选择结构:根据条件的不同有选择的执行不同的代码循环结构:在一定条件下 反复执行某一片代码
- 规则1(无继承情况下):对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是(静态变量、静态初始化块)>(变量、
- 一、TkMybatisTkmybatis 是基于 Mybatis 框架开发的一个工具,通过调用它提供的方法实现对单表的数据操作,不需要写任何
- Code CacheJVM生成的native code存放的内存空间称之为Code Cache;JIT编译、JNI等都会编译代码到nativ
- Java栈之链式栈存储结构实现一、链栈采用单链表来保存栈中所有元素,这种链式结构的栈称为链栈。二、栈的链式存储结构实现package com
- 1、首先看一下下面两个sql语句的区别:<select id="selectByNameAndPassword"
- 相关知识:Java中三种简单注解介绍和代码实例一、作用用 @Deprecated注解的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危
- Android自带的跑马灯效果不太好控制,还必须要满足条件才能有效果,而且速度不受控制。前面我的博客中有一篇就是用Android自带的跑马灯
- 项目地址:gitee.com/baojh123/rp…netty-study 这个项目是没用到的,可以删掉,主要是测试
- 当数据库中数据条数过多时,一个页面就不能显示,这是要设置分页查询,首先要使用的是数据库sql语句的limit条件实现分组查询sql语句大概形
- WebService是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Interne
- 最近在研究dubbo时,发现了JAVA的SPI特性。SPI的全名为Service Provider Interface,是JDK内置的一种服
- maven 常见命令配置maven常用命令#创建项目 -D设置参数mvn archetype:generate -DgroupId=cn.d
- 适配器(Adapter)模式:适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一
- 实践过程效果代码public partial class Form1 : Form{ public Form1()
- Java 方法执行时的动态分派和静态分派是 Java 实现多态的本质背景Java 的动态分派和静态分派也是 Java 方法的执行原理。 Ja
- 引言一个复杂的分布式系统,用户发起一个请求,这个请求可能调用几十到几百个服务,经过很多业务层,而每个业务又是多个机器集群,一个请求具体被随机
- 背景大家在使用Selenium + Chromedriver爬取网站信息的时候,以为这样就能做到不被网站的反爬虫机制发现。但是实际上很多参数
- 泛型是Java中一个非常重要的内容,对于Java进阶学习是必须要掌握的知识点之所以说这个知识点重要,如果你有过阅读过一些开源框架的代码,那你
- 摘要本文主要介绍基于SpringBoot定时任务ScheduledTaskRegistrar的动态扩展,实现定时任务的动态新增和删除。Sch