在Kotlin中的功能循环中,如何做“休息”或“继续”?
在Kotlin中,我不能在函数循环和lambda中continue
break
或continue
,就像我可以从一个普通的for
循环一样。 例如,这不起作用:
(1..5).forEach { continue@forEach // not allowed, nor break@forEach }
有一些旧的文档提到这个可用,但它似乎从来没有实现。 当我想要在lambda内continue
或break
时,获得相同行为的最佳方法是什么?
注意: 这个问题是由作者故意写的和回答的( 自我回答的问题 ),所以对于常见的Kotlin话题的习惯性的回答是在SO中。 此外,为了澄清一些真正的古老的答案写为科特林的阿尔法,是不是今天的Kotlin准确。
您可以使用lambda表达式的返回,它根据您的使用情况模仿continue
或break
。
这是一个模仿continue
的例子:
(1..5).forEach { if (it == 3) return@forEach // mimic continue@forEach // ... do something more }
如果您遇到嵌套或混乱的情况,您可以更加复杂并使用标签:
(1..3).forEach outer@ { x -> (1..3).forEach inner@ { y -> if (x == 2 && y == 2) return@outer // mimic continue@outer if (x == 1 && y == 1) return@inner // mimic continue@inner // ... do something more } }
如果你想break
你需要一些你可以返回的东西,在这里我们将使用run()
函数来帮助我们:
run breaker@ { (1..20).forEach { x -> if (x == 5) return@breaker // mimic break@forEach // ... do something more } }
而不是run()
它可以是let()
或apply()
或任何你自然拥有的围绕forEach
的地方,这是你想要摆脱的地方。 但是你也可以跳过forEach
之后的代码块,所以要小心。
这些是内联函数,所以真的不会真正增加开销。
阅读所有特殊情况(包括匿名函数)的Kotlin参考文档,了解返回和跳转 。
这是一个单元测试,证明了这一切的作品:
@Test fun testSo32540947() { val results = arrayListOf<Pair<Int,Int>>() (1..3).forEach outer@ { x -> (1..3).forEach inner@ { y -> if (x == 2 && y == 2) return@outer // continue @outer if (x == 1 && y == 1) return@inner // continue @inner results.add(Pair(x,y)) } } assertEquals(listOf(Pair(1,2), Pair(1,3), Pair(2,1), Pair(3,1), Pair(3,2), Pair(3,3)), results) val results2 = arrayListOf<Int>() run breaker@ { (1..20).forEach { x -> if (x == 5) return@breaker results2.add(x) } } assertEquals(listOf(1,2,3,4), results2) }
forEach
可以用任何 函数来具体替换:
(1..20).any { x -> (x == 5).apply { // break on true if (!this) { results2.add(x) } } }
甚至可能更短:
(1..20).any { x -> results2.add(x) x == 4 // break on true }
takeWhile stdlib函数可能被用来代替break。
例如,
val array = arrayOf(2, 8, 4, 5, 13, 12, 16) array.takeWhile { it % 2 == 0 }.forEach { println(it) } // break on odd array.takeWhile { it % 3 != 0 }.forEach { println(it) } // break on 3 * n