HashSet.remove()无法按照规范行事?

时间:2014-11-15 16:57:56

标签: java set

根据HashSet的JDK文档,remove():

  

删除元素e,使得(o == null?e == null:o.equals(e)),如果   这个集合包含这样一个元素。

嗯,这里有一小部分代码证明不是这样。 Set点肯定包含我的观点,如equals()所示,然而,remove()神秘地无法删除它。麻烦似乎是由于point.x的值的变化(main()的第4行)。省略这一点会使一切都按预期运行。

请注意,如果points是ArrayList而不是HashSet,则以下行为正常。

import java.awt.geom.Point2D;
import java.util.Collection;
import java.util.HashSet;

public class RemoveTest2 {

    public static void main(final String[] args) {
        final Collection<Point2D.Double> points = new HashSet<Point2D.Double>();
        final Point2D.Double point = new Point2D.Double();
        points.add(point);
        point.x++;

        // make sure that points definitely contains the point we are trying to remove...
        for (final Point2D.Double p : points) {
            if (point.equals(p)) {
                System.out.println("points definitely contains " + point);
                System.out.println(point.hashCode() + " == " + p.hashCode());
            }
        }

        if (!points.remove(point)) {
            System.out.println("and yet... failed to remove " + point);
        }
        System.out.println("points cointains " + points.size());
    }

}

规范看起来很痛苦......请有人向我解释我在这里缺少的东西。

1 个答案:

答案 0 :(得分:2)

问题是您在使用对象后更改了对象的哈希码,因此Hashset无法使用新的哈希码获取现有对象(因为它使用旧的哈希码存储)。

更改此类字段时,您需要先删除此对象,然后再更改它,而不是再次存储它。

查看this