为什么 hashCode() return 零导致 List.minus() 到 return 一个空列表?
Why does a hashCode() returning zero cause List.minus() to return an empty list?
鉴于 class 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
minus()
的结果是一个空列表。如果我将 hashCode() 实现切换为 return name.hashCode()
,则断言通过。对于任一实现,contains()
等方法都按预期工作。
我的问题是不是如何实现更好的hashCode(),而是为什么minus()
会这样。
这正是 docs for minus:
中描述的行为
Create a List composed of the elements of the first list minus every occurrence of elements of the given Collection.
assert [1, "a", true, true, false, 5.3] - [true, 5.3] == [1, "a", false]
您删除了第二个列表中的每个元素。在您的情况下,从 [f1,f2] 中删除所有 f3,其中所有内容都相同,因此列表为空。
更详细的信息在 DefaultGroovyMethods.minus
and then in NumberAwareComperator
, which uses the hashCode
. as you have already found, there are open tickets regarding this (https://jira.codehaus.org/browse/GROOVY-7158) 中。所以在眼皮底下,那里使用了 hashCode
,行为是完全一致的……应该在那里使用吗?也许不是,因为在某些情况下,它真的很奇怪(例如 [[x:0,y:0]]-[[x:1,y:1]]==[]
)。
案例 [f1,f2]-f3
在代码中采用了另一条路线,因此行为不同。
现在我最好的猜测是,您将 minus
用于不可变类型(如上面的示例),它工作得很好。除此之外,更喜欢使用集合。
java 集合使用 hashCode/equals
的实现来确定对象相等性。您实施的 hashCode
表示 f1
、f2
和 f3
都是 "the same"。松散地说:
[f1, f2] - [f3]
可以读作
Remove from the list all objects that are the same as f3
所以它删除了所有对象。
您似乎已经意识到这是实现 hashCode
的糟糕方式,因此它实际上只是 "garbage in, garbage out".
的一个例子
鉴于 class 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
minus()
的结果是一个空列表。如果我将 hashCode() 实现切换为 return name.hashCode()
,则断言通过。对于任一实现,contains()
等方法都按预期工作。
我的问题是不是如何实现更好的hashCode(),而是为什么minus()
会这样。
这正是 docs for minus:
中描述的行为Create a List composed of the elements of the first list minus every occurrence of elements of the given Collection.
assert [1, "a", true, true, false, 5.3] - [true, 5.3] == [1, "a", false]
您删除了第二个列表中的每个元素。在您的情况下,从 [f1,f2] 中删除所有 f3,其中所有内容都相同,因此列表为空。
更详细的信息在 DefaultGroovyMethods.minus
and then in NumberAwareComperator
, which uses the hashCode
. as you have already found, there are open tickets regarding this (https://jira.codehaus.org/browse/GROOVY-7158) 中。所以在眼皮底下,那里使用了 hashCode
,行为是完全一致的……应该在那里使用吗?也许不是,因为在某些情况下,它真的很奇怪(例如 [[x:0,y:0]]-[[x:1,y:1]]==[]
)。
案例 [f1,f2]-f3
在代码中采用了另一条路线,因此行为不同。
现在我最好的猜测是,您将 minus
用于不可变类型(如上面的示例),它工作得很好。除此之外,更喜欢使用集合。
java 集合使用 hashCode/equals
的实现来确定对象相等性。您实施的 hashCode
表示 f1
、f2
和 f3
都是 "the same"。松散地说:
[f1, f2] - [f3]
可以读作
Remove from the list all objects that are the same as f3
所以它删除了所有对象。
您似乎已经意识到这是实现 hashCode
的糟糕方式,因此它实际上只是 "garbage in, garbage out".