更改集合中的元素会更改“等于”语义 [英] Changing the elements in a set changes the 'equals' semantics
问题描述
想象一下,我们有这段代码。
Imagine that we have this piece of code.
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生成的。
I didn't put the code for hashCode() and equals() due to space constraints, but it's the one generated from Eclipse.
问题是在更改两个集合中的元素之前,集合是平等的。在更改它们的值(每个值为相同的值)之后,这些集不再相等,尽管e1.hashCode()== e2.hashCode()和e1.equals(e2)。
The problem is that before changing the elements in the two sets, the sets are equal. After changing their values (each to the same value), the sets are not equal anymore, although e1.hashCode() == e2.hashCode() and e1.equals(e2).
我猜测在比较两个HashSets时,Java使用元素的原始hashCode(插入时的那个)。因此,在插入后更改元素会更改其原始的hashCode,因此contains()将返回false。
I'm guessing that when comparing two HashSets, Java uses the original hashCode of the element (the one at the moment of insertion). So, changing the elements after insertion changes their original hashCode, and therefore contains() will return false.
在我看来,这是一种非常不直观的行为。
In my opinion this is a very unintuitive behaviour.
你怎么看?
推荐答案
这正是预期的行为。 Set
实现没有办法知道元素的 hashCode
已经改变了,所以什么也没有它可以防止这种可能性。
This is exactly the expected behavior. There is no possible way for a Set
implementation to be aware that the hashCode
of an element has changed, so there's nothing it can do to defend against that possibility.
来自设置
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.
这篇关于更改集合中的元素会更改“等于”语义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!