我试图在groovy中使用递归来遍历树关系.下面的代码运行一个循环,直到childNodes && recurClosure(childNodes),但不会再次调用闭包recurClosure.在那一瞬间,childNodes有两个与root相同的对象(数组列表).
在代码中,定义了recurClosure并使用对象列表(root)进行调用.然后迭代遍历每个元素并对子节点进行罚款(为此使用grails dsl).如果childNodes不为null,则递归调用父方法.
我应该分手,还是出了什么问题?
def parentval
def root = Domain.list()
def recurClosure
recurClosure = {inroot ->
inroot.each {
returnList << it
parentval = it
childNodes = Domain.withCriteria {
eq('parent', parentval )
}
}
childNodes && recurClosure(childNodes )
}(root)
return returnList
Run Code Online (Sandbox Code Playgroud)
}
提前致谢.
更新:注意到以下异常
ERROR [2010-06-24 08:20:04,742] [groovy.grails.web.errors.GrailsExceptionResolver] Cannot invoke method call() on null object
java.lang.NullPointerException: Cannot invoke method call() on null object
at com.bsr.test.DomainService$_closure2_closure7.doCall(com.bsr.test.DomainService:68)
at com.bsr.test.DomainService$_closure2.doCall(com.bsr.test.DomainService:58)
at com.bsr.test.DomainController$_closure3.doCall(DomainController.groovy:45)
at com.bsr.test.DomainController$_closure3.doCall(DomainController.groovy)
at org.apache.shiro.web.servlet.ShiroFilter.executeChain(ShiroFilter.java:687)
at org.apache.shiro.web.servlet.ShiroFilter.doFilterInternal(ShiroFilter.java:616)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81)
at java.lang.Thread.run(Thread.java:619)
Run Code Online (Sandbox Code Playgroud)
更新2:现在尝试丹尼尔的建议.
{ inroot ->
inroot.each {
returnList << it
parentval = it
childNodes = Domain.withCriteria {
eq('parent', parentval )
}
if(childNodes)
call(childNodes)
}
/*if(childNodes)
call(childNodes)*/
}(root)
Run Code Online (Sandbox Code Playgroud)
在上面的实现中,root是一个arraylist,内部闭包从它中取出每个元素并递归调用匿名闭包.当我在每个闭包内部移动'call'时,它不会调用外部匿名闭包,而是调用inroot.each {}本身.所以,我得到一个错误
ERROR [2010-06-24 08:47:46,438] [groovy.grails.web.errors.GrailsExceptionResolver] instance not of expected entity type: java.util.ArrayList is not a: com.bsr.test.Domain
Run Code Online (Sandbox Code Playgroud)
我看到一篇关于如何通过'this'命名关闭的博客文章>我将更新我的发现..谢谢
更新3:调用外部闭包的方法是owner.call(childNodes)
Dan*_*ser 10
问题是,通过
recurClosure = {
[...]
}(root)
Run Code Online (Sandbox Code Playgroud)
你不分配闭包recurClosure
,而是分配它的调用的返回值!因此,当然,你不能通过recurClosure()
... 来调用闭包.
两种可能的解决方
首先定义闭包,然后单独调用它,如air_blob建议:
def recurClosure = {
[...]
}
recurClosure(root)
Run Code Online (Sandbox Code Playgroud)
使用隐式call()
函数进行递归.这样你甚至可以使用匿名闭包.恕我直言在Groovy中实现递归的一种非常好的方法:
{ inroot ->
inroot.each {
returnList << it
parentval = it
childNodes = Domain.withCriteria {
eq('parent', parentval )
}
}
if(childNodes)
call(childNodes)
}(root)
Run Code Online (Sandbox Code Playgroud)
还有两条关于代码的评论:
returnList
:def returnList = []
childNodes && recurClosure(childNodes )
可以做你想要的,但是更多的可读性可以牺牲一个更多的字符并拼出if
... ;-)each
?您的代码的另一个(更高级别)评论:如果父母和他们的孩子属于同一类型(Domain
),Domain.list()
实际上也不会归还所有孩子吗?是否真的需要手动遍历树?
归档时间: |
|
查看次数: |
4133 次 |
最近记录: |