闭包在Groovy 的类型是 groovy.lang.Closure,是Groovy的一大利器。
闭包可以视为代码块、语句块、可以访问周围范围内的所有变量或方法。
def z = {
println "hello" }
z()
很简单,闭包只是一个语句,用大括号包含。您可以将其分配给变量,然后像常规方法调用一样调用此闭包。闭包具有一个默认的隐式参数,称为it
。还可以提供自定义的参数。同样,就像方法中的情况一样,闭包的最后一个表达式是闭包的返回值。但是,如果您觉得可读性更高,也可以使用return
关键字。
def square = {
it * it }
assert square(3) == 9
def lengthThan = {
String s, int i -> return s.size() > i }
//def lengthThan = { String s, int i -> s.size() > i }
assert lengthThan("FunTester", 4) == true
assert lengthThan("Fun", 6) == false
函数执行之后内部变量全部销毁,但是闭包不会,闭包的外部变量会一直保存。
def static add(num) {
def sum = 0
sum += num
return sum
}
def static addByClosure(init) {
def addInner = {
inc ->
init += inc
init
}
return addInner
}
println "one call: ${add(5)}" // one call: 5
println "two call: ${add(5)}" // two call: 5
def addClosure = addByClosure(0)
println "one call: ${addClosure(5)}" // one call: 5
println "two call: ${addClosure(5)}" // two call: 10
闭包可以这样写:
def hello = 'Hello'
def clos = {
param -> println "${hello},${param}"
}
def clos2 = {
p1,p2 -> println "the parameters are ${p1} and ${p2}"
}
def exec(clo){
clo('wzy')
}
//闭包的调用方式
clos.call('zhh')
clos('zhh')
clos'zhh'
clos2(1,2)
exec(clos)
exec clos
exec{
param -> println "hellooo, ${param}"
}
输出结果:
Hello,zhh
Hello,zhh
Hello,zhh
the parameters are 1 and 2
Hello,wzy
Hello,wzy
hellooo, wzy
1.upto(5){
println"abc"
}
def count = 0
1.upto(4){
pp -> count +=pp
}
println "count:${count}"
输出:
abc
abc
abc
abc
abc
count:10
each方法常常用于列表、映射和字符串,以遍历每个元素,并将闭包应用于每个元素
[1,2].each{
println it
}
['zhangsan':21,'lisi':22].each{
println it
}
['zhangsan' : 21, 'lisi' : 22].each {
println "${it.key} maps to :${it.value}"
}
['zhangsan' : 21, 'lisi' : 23].each {
p -> if(p.value>22){
println "${p.key} value over 22"
}else{
println "${p.key} value low 23"
}
}
输出
1
2
zhangsan=21
lisi=22
zhangsan maps to :21
lisi maps to :22
zhangsan value low 23
lisi value over 22
find方法返回集合中符合某个判断标准的第一个值,若不存在则符合null。在闭包中,集合元素使用的判断条件必须是布尔表达式。
def f = [1,2].find{
it -> it>1
}
println "find :${f}"
输出
find :2
findAll方法将遍历所有元素,并返回一个符合条件的列表。
def fa = ['zhangsan':21,'lisi':23,'wangwu':24].findAll{
it -> it.value>22
}
println "find all :${fa}"
fa.each{
println it
}
[1,2,3].findAll{
it -> it>1
}.each{
println it
}
输出:
find all :[lisi:23, wangwu:24]
lisi=23
wangwu=24
2
3
any方法将遍历检查集合的每个元素,以确认:对至少一个元素来说,由闭包提供的布尔断言是否合法。
def a = [1,2].any{
it -> it >1
}
println "any one over 1?${a}"
输出
any one over 1?true
every方法则用来检查:对集合的所有元素来首,闭包提供的布尔断言是否合法。
def a = [1,2].every{
it -> it>1
}
println "every one over 1?${a}"
输出
every one over 1?false
collect方法将遍历某个集合,并使用闭包中的变换方法将集合中的每个元素转换为一个新值。返回一个由转换后的值所组成的列表。
def list = [1,2,3,4].collect{
it -> return it * it
}
println "list: ${list}"
list = (0..2).collect{
it -> 2 * it
}
println "list:${list}"
list = (0..<2).collect{
it -> 3 *it
}
println "list:${list}"
def s = ['zhangsan':21,'lisi':22]
list = s.collect{
it -> ++it.value
}
def olderS = s.collect{
it -> ++it.value
return it
}
println "s:${s}"
println "list: ${list}"
println "olderS: ${olderS}"
输出
list: [1, 4, 9, 16]
list:[0, 2, 4]
list:[0, 3]
s:[zhangsan:23, lisi:24]
list: [22, 23]
olderS: [zhangsan=23, lisi=24]
inject方法可用于遍历集合,首先将需要传递的初始值和集合项目传递给闭包,此时其传递的初始值将作为初始结果,然后再和下一个集合元素一起传给闭包,以此类推。
def factorial = [2,3,4].inject(1){
previous,element ->
println "pre:${previous},ele:${element}"
previous * element
}
println "facotria(4): ${factorial}"
输出
pre:1,ele:2
pre:2,ele:3
pre:6,ele:4
facotria(4): 24
def multiply(x){
return{
y -> return x * y
}
}
def twice = multiply(2)
println "twice(3) = ${twice(3)}"
输出
twice(3) = 6
def swap = {
sList, p, q ->
def temp = sList[p]
sList[p] = sList[q]
sList[q] = temp
}
def minPosition = {
pList, from ->
def mPos = from
def nextFrom = from + 1
for (i in nextFrom..<pList.size()) {
if (pList[i] < pList[mPos]) {
mPos = i
}
}
return mPos
}
def selectionSort = {
l ->
def size = l.size() - 1
for (j in 0..<size) {
def minPos = minPosition(l, j)
swap(l, minPos, j)
}
return l
}
def table = [2, 4, 1, 3]
def sorted = selectionSort(table)
println "sorted : ${sorted}"
输出
sorted : [1, 2, 3, 4]
参考网上大神:https://blog.csdn.net/zhangyongfeiyong/article/details/53127092