详解Kotlin:forEach也能break和continue

网友投稿 707 2023-05-07


详解Kotlin:forEach也能break和continue

详解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) {

(0..100).forEach {

if (50 <= it) return@fKwKwNbeYorEach

println(it)

}

}

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

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

fun Pair.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) {

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[] argsKwKwNbeY)

{

http:// 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了。服不服?

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:微信小程序实现多个按钮toggle功能的实例
下一篇:mock工具原理(mock原理图)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~