有没有办法“打破”一个常规的封闭。
可能是这样的:
[1, 2, 3].each {
println(it)
if (it == 2)
break
}
答案 0 :(得分:21)
我经常忘记Groovy实现了“任何”方法。
[1, 2, 3].any
{
println it
return (it == 2)
}
答案 1 :(得分:13)
12/05/2013重编辑。
回答问题。
是否可以突破关闭?
您可以通过发出return
关键字来“中断”。但是,这在给出的示例中没有帮助。这样做的原因是,对于集合中的每个项,each
方法都会调用闭包(将其视为方法)。
如果您运行此示例,您将看到它将打印1然后3。
[1, 2, 3].each {
if (it == 2) return
println(it)
}
为什么在break
的上下文中each
没有意义。
要理解为什么你不能突破each
方法,就像你可以突破for
循环一样,你需要了解一些实际发生的事情。这是对集合中每个方法的粗略简化。
myEach([0,1,3])
void myEach(List things) {
for (i in things) {
myEachMethod(i)
}
}
void myEachMethod(Object it) { // this is your Closure
if(it == 2) return
println it
}
正如您所看到的,闭包基本上是一种可以传递的方法。就像在java中一样,你不能在方法调用或闭包中断开。
该怎么做而不是与each
分开。
在Groovy中,您应该使用高级抽象来表达您的代码,因为原始循环不是惯用的。对于您给出的示例,我会考虑使用findAll。例如:
[1,2,3].findAll { it < 2 }.each { println it }
我希望这有助于您了解正在发生的事情。
回答隐含的问题。
你可以针对提供的闭包进行
Collection.each
次迭代吗?
John Wagenleitner所说,如果不抛弃和捕捉异常,你就无法摆脱each
方法。虽然我认为在流量控制名称中抛出和捕获异常是一种代码气味,同事程序员可能会拍你的手。
答案 2 :(得分:8)
你可以抛出异常:
try {
[1, 2, 3].each {
println(it)
if (it == 2)
throw new Exception("return from closure")
}
} catch (Exception e) { }
使用也可以使用“findAll”或“grep”过滤掉你的列表,然后使用“each”。
[1, 2, 3].findAll{ it < 3 }.each{ println it }
答案 3 :(得分:8)
答案 4 :(得分:7)
尝试使用任何而不是每个
def list = [1, 2, 3, 4, 5, -1, -2]
list.any { element ->
if (element > 3)
return true // break
println element
}
结果: 1,2,3
答案 5 :(得分:3)
还有另一种解决方案。虽然,像每个/ find / any这样的常规东西很酷:如果它不合适,不要使用它。你仍然可以使用普通的
for (def element : list)
特别是,如果你想离开这个方法的话。现在您可以随意使用continue / break / return。结果代码可能不太酷,但它很容易理解。
答案 6 :(得分:2)
这是对John Wagenleiter的回答的支持。 Tigerizzy的答案是完全错误的。通过执行他的第一个代码示例,或理论上通过阅读Groovy文档,可以很容易地反驳它。 return 从当前迭代返回一个值(或不带参数的null),但不会停止迭代。在闭包中,它的行为与 continue 相似。
如果不理解这一点,您将无法使用注入。
除了抛出异常之外,没有办法“打破循环”。为此目的使用例外被认为是臭的。因此,正如Wagenleiter建议的那样,最好的做法是在启动每个或其中一个表兄弟之前过滤掉你想要迭代的元素。
答案 7 :(得分:2)
只需使用特殊关闭
// declare and implement:
def eachWithBreak = { list, Closure c ->
boolean bBreak = false
list.each() { it ->
if (bBreak) return
bBreak = c(it)
}
}
def list = [1,2,3,4,5,6]
eachWithBreak list, { it ->
if (it > 3) return true // break 'eachWithBreak'
println it
return false // next it
}
答案 8 :(得分:0)
使用rx-java,您可以将可迭代变换为可观察的。
然后你可以用过滤器替换 continue ,用 takeWhile 替换 break
以下是一个例子:
import rx.Observable
Observable.from(1..100000000000000000)
.filter { it % 2 != 1}
.takeWhile { it<10 }
.forEach {println it}