Groovy 为什么返回零的hashCode()会导致List.减号()返回空列表?

Groovy 为什么返回零的hashCode()会导致List.减号()返回空列表?,groovy,hashcode,Groovy,Hashcode,给定类Foo的hashCode()实现非常糟糕: class Foo { String name public int hashCode() { 0 } public boolean equals(Object obj) { if (obj == null) { return false } if (!(obj instanceof Foo)) {

给定类Foo的hashCode()实现非常糟糕:

class Foo {
    String name

    public int hashCode() {
        0
    }

    public boolean equals(Object obj) {
        if (obj == null) {
            return false
        }

        if (!(obj instanceof Foo)) {
            return false
        }
        Foo foo = (Foo) obj
        return this.name.equals(foo.name)
    }   
}
为什么下面的断言失败了

Foo f1 = new Foo(name: 'Name 1')
Foo f2 = new Foo(name: 'Name 2')
Foo f3 = new Foo(name: 'Name 2')
assert ([f1, f2] - [f3]).size() == 1
减号()的结果是一个空列表。如果我将hashCode()实现切换到
return name.hashCode()
,断言就会通过。无论是哪种实现,像
contains()
这样的方法都能按预期工作


我的问题不是如何实现更好的hashCode(),而是为什么
减号()
会有这样的行为。

这正是以下内容中描述的行为:

创建一个由第一个列表中的元素减去给定集合中每一个元素组成的列表

assert [1, "a", true, true, false, 5.3] - [true, 5.3] == [1, "a", false]
删除第二个列表中的每个元素。在您的例子中,从[f1,f2]中删除所有f3,其中所有f3都相同,因此为空列表

更精细的细节在中,然后在中,使用
hashCode
。正如您已经发现的,有关于此()的公开票证。因此,在这里使用的是
hashCode
,行为完全一致。。。应该在那里使用吗?也许不是,因为在某些情况下,它确实变得很奇怪(例如,
[[x:0,y:0]]-[[x:1,y:1]]=[]

案例
[f1,f2]-f3
在代码中采用另一条路径,因此行为不同


现在我最好的猜测是,对于不可变的类型(如上面的示例),使用
减号
,效果非常好。除此之外,更应该使用集合。

java集合使用
hashCode/equals的实现来确定对象相等性。对
hashCode
的实现表明
f1
f2
f3
都是“相同的”。粗略地说:

[f1, f2] - [f3]
可以理解为

从列表中删除与f3相同的所有对象

因此,它会删除所有对象


您似乎已经意识到,这是一种可怕的实现
hashCode
的方法,所以这实际上只是一个“垃圾输入,垃圾输出”的例子+1尽管如此,如果我们只是执行
[f1,f2]-f3
:,则不会发生这种情况在这种情况下,
equals()
是如何考虑的?我在equals/hashCode契约中的假设是,当对象满足
equals()
契约时,它们的hashCode必须相等。但是,具有相同hashCode的对象不一定相等,因为如果对象实现了
Comparable
,则它只使用
numberAwareCompare
。然后改为使用
DefaultTypeTransformation.compareEqual(o1,o2)
,它逐渐依赖于对象本身的
equals
方法。正是在这个时候。:)看起来像是识别了@cfrick在回答中提到的缺陷:
NumberAwareComparator