更改集合中的元素会更改“等于”语义 [英] Changing the elements in a set changes the 'equals' semantics

查看:173
本文介绍了更改集合中的元素会更改“等于”语义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下,我们有这段代码。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆