问题描述
我正在尝试使用 Groovy 检索两个列表中的公共项目。以下代码工作正常,即运行此代码的输出是“在公共项目中找到的调试:相同”。到目前为止一切顺利!
def list1 = ["same","different"]
def list2 = ["same","not the same"]
def commonItems = list1.intersect(list2)
for(int i=0; i < commonItems.size(); i++)
{
log.info("DEBUG found in common Items : " + commonItems[i])
}
当我尝试将上述原则应用于对象列表时遇到了一个问题 - 我的问题是“commonItems”列表不包含我期望的单个对象,而是空的。请注意,我的自定义对象“ErrorWarningDetail”确实覆盖了 compareto。有人可以看到我做错了什么/提出任何建议吗?提前致谢!
首先这里是我的自定义类 - 注意“Compateto”现在只检查“代码”字段。
class ErrorWarningDetail implements Comparable
{
public String Code
public String Description
public String ErrorType
public String State
@Override
int compareto(Object o) {
int result = Code <=> o.Code
result
}
}
现在是执行业务的代码。我希望一个对象在 'commonItems' 中,但它实际上是空的 - 我在这里做错了什么?运行这个的输出是“DEBUG no common items”
def similarONE = new ErrorWarningDetail()
similarONE.Code = "100-1"
def similarTWO =new ErrorWarningDetail()
similarTWO.Code = "100-1"
def completelyDifferent = new ErrorWarningDetail()
completelyDifferent.Code = "697-2"
def List1 = []
def List2 = []
List1.add(similarONE)
List1.add(completelyDifferent)
List2.add(similarTwo)
def commonItems = list1.intersect(list2)
if (commonItems.size() == 0)
{
log.info("DEBUG no common items")
}
解决方法
在 Java 中实现 compareTo()
是不够的,您应该实现 equals/hashCode。
在 Groovy 中有一个方便的注释。所以,下面的脚本成功执行:
import groovy.transform.EqualsAndHashCode
@EqualsAndHashCode( includes = [ 'code' ] )
class ErrorWarningDetail implements Comparable {
String code
String description
String errorType
String state
@Override
int compareTo(Object o) {
code <=> ( o?.code ?: '' )
}
}
def similarONE = new ErrorWarningDetail( code:"100-1" )
def similarTWO = new ErrorWarningDetail( code:"100-1" )
def completelyDifferent = new ErrorWarningDetail( code:"697-2" )
def list1 = [similarONE,completelyDifferent]
def list2 = [similarTWO]
def commonItems = list1.intersect list2
assert 1 == commonItems.size()
附言请不要命名以大写字母开头的字段!
,equals
和 hashCode
是用于确定对象相等性的方法,因此 intersect 方法将依赖于这些方法。
compareTo
方法用于排序目的。
Groovy 在包 groovy.transform
下面是修改后的类,带有注释,使其按预期工作。
@EqualsAndHashCode(includes=["Code"])
@ToString(includeFields=true)
class ErrorWarningDetail implements Comparable
{
String Code
String Description
String ErrorType
String State
@Override
int compareTo(Object o) {
Code <=> o?.Code
}
}