假设我们有这段代码。
public class HashAddAfter {
private class A {
public int value;
public A(int value) {
this.value = value;
}
public void setValue(int value) {
this.value = value;
}
// Code for hashCode()...
// Code for equals()...
}
Set<A> list1 = new HashSet<A>();
Set<A> list2 = new HashSet<A>();
public static void main(String[] args) {
HashAddAfter x = new HashAddAfter();
A e1 = x.new A(1);
A e2 = x.new A(1);
x.list1.add(e1);
x.list2.add(e2);
System.out.println(x.list1.equals(x.list2)); // true
e1.setValue(4);
e2.setValue(4);
System.out.println(x.list1.equals(x.list2)); // false
}
}
由于空间限制,我没有放 hashCode() 和 equals() 的代码,但它是从 Eclipse 生成的代码。
问题是在改变两个集合中的元素之前,集合是相等的。在更改它们的值(每个值都相同)后,集合不再相等,尽管 e1.hashCode() == e2.hashCode() 和 e1.equals(e2)。
我猜测在比较两个 HashSet 时,Java 使用元素的原始 hashCode(插入时的那个)。因此,在插入后更改元素会更改其原始哈希码,因此 contains() 将返回 false。
在我看来,这是一种非常不直观的行为。
你怎么看?
最佳答案
这正是预期的行为。 Set
实现不可能知道元素的 hashCode
已更改,因此它无法采取任何措施来抵御这种可能性。
来自集合
Javadoc :
Note: Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set. A special case of this prohibition is that it is not permissible for a set to contain itself as an element.
关于java - 更改集合中的元素会更改 'equals' 语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16402970/