我有一个这样的函数:
private downloadAllFiles() {
sftpRetriever.listFiles().findAll {
filter.isResponse(it) || filter.isResponseTurned(it)
}.each { String fileName ->
log.info 'Downloading file: {}', fileName
sftpRetriever.downloadFile(fileName)
log.info 'File downloaded'
removeRemoteFile(fileName)
}
}
我正在寻找一种简单的方法来在该函数中修改这个闭包,所以如果findAll的size()为0,它只会记录"没有更多的文件要下载"和.每个都不会被执行。有没有什么简单的方法可以使它在单个闭包中?如果我把它分成几个部分,这真的很简单,但要尝试在这里学习闭包并提高我的表达能力:)提前感谢您的帮助。
看看下面的生物:)它之所以有效,是因为each
返回了调用它的集合(+elvis运算符和相当不错的Groovy真值评估):
def printContents(Collection collection) {
collection.each {
println it
} ?: println('Collection is empty')
}
printContents([1,2,'hello'])
printContents([])
我不喜欢这种语法,但我想到的是较短的版本。
您还可以使用元编程来添加Steinar提供的方法。在第一次使用之前,它必须添加到metaClass
中,但您将避免制作扩展模块:
Collection.metaClass.doIfEmpty { Closure ifEmptyClosure ->
if (delegate.empty) {
ifEmptyClosure()
}
return delegate
}
def printContents(Collection collection) {
collection.doIfEmpty {
println "Collection is empty"
}.each {
println it
}
}
printContents([1,2,'hello'])
printContents([])
一个相当通用且可重复使用的选项是使用扩展模块扩展Collection
。这非常容易做到,甚至在IDE中也能识别(至少在IntelliJ中),因此您可以完成代码等。
例如,为集合编写一个扩展类,如果集合为空,它将执行闭包。此外,它应该始终返回集合以允许进一步的链接:
package stackoverflow
class CollectionExtension {
static <T extends Collection> T doIfEmpty(T self, Closure closure) {
if (self.empty) {
closure()
}
return self
}
}
您还需要告诉groovy这个文件是一个扩展模块。在类路径上添加一个属性文件作为资源:META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
(注意:这个名称和位置对于扩展模块是强制性的,即您不能更改它)。
moduleName=stackoverflow-module
moduleVersion=1.0
extensionClasses=stackoverflow.CollectionExtension
最后是一个简单的测试脚本来展示如何使用它:
def printContents(Collection collection) {
collection.doIfEmpty {
println "Collection is empty"
}.each {
println it
}
}
printContents([1,2,'hello'])
printContents([])
输出:
1
2
hello
Collection is empty
您可以尝试以下代码:
def l1 = [1,2,3,4]
def l2 = [5,6,7,8]
def m(list) {
list.findAll { it < 5}.with { l ->
size > 0 ?
l.each { e ->
println e
}
:
println('Zero elements found')
}
}
m(l1)
m(l2)
目前没有更好的主意。