开发者

Objects equal, hashcodes equal, HashSet contains one but not the other---how?

开发者 https://www.devze.com 2023-02-18 15:59 出处:网络
I have an (immutable) object, Group, which I am trying to use in a HashSet. However, I am getting odd results:

I have an (immutable) object, Group, which I am trying to use in a HashSet. However, I am getting odd results:

// Position is another immutable class, GroupType is an enum
Group t1 = new Group(new Position(0, 0), GroupType.ROW);
Group t2 = new Group(new Position(0, 0), GroupType.RO开发者_开发技巧W);
Set<Group> s = new HashSet<Group>();
s.add(t1);
System.out.format("t1.hashCode(): %d\nt2.hashCode(): %d\nt1.hashCode() == t2.hashCode(): %b\nt1.equals(t2): %b\nt2.equals(t1): %b\ns.contains(t1): %b\ns.contains(t2): %b\n",
    t1.hashCode(),
    t2.hashCode(),
    t1.hashCode() == t2.hashCode(),
    t1.equals(t2),
    t2.equals(t1),
    s.contains(t1),
    s.contains(t2)
    );

results in the following:

t1.hashCode(): 486656595
t2.hashCode(): 486656595
t1.hashCode() == t2.hashCode(): true
t1.equals(t2): true
t2.equals(t1): true
s.contains(t1): true
s.contains(t2): false

t1 and t2 have identical hashcodes, and equals() claims that they are the same. How can the HashSet contain one and not the other?

(And no, none of those methods are secretly modifying t1 or t2; repeating the print statement garners the same results.)

Group.equals() is as follows:

public boolean equals(Group g2) {
    return (this.type.equals(g2.type)) && (this.basis.equals(g2.basis));
}

type is a (final) enum stored. basis is a Position, which has the following equals:

public boolean equals(Position pos) {
    return (x == pos.x) && (y == pos.y);
}

where x and y are internal, final variables.

However, I get the same results replacing it with:

public boolean equals(Group g2) {
    return true;
}


I have a suspicion... my guess is that your equals method looks like this:

public boolean equals(Group other)

That's not overriding the built-in equals method, which is what HashSet will use. Make sure your equals method is:

@Override // Make the compiler check we're overriding something
public boolean equals(Object other)

Another way of testing this is:

Object o1 = t1;
Object o2 = t2;

System.out.println(o1.equals(o2));
System.out.println(o2.equals(o1));


it's a set. it will not add another element that is equal to an existing element. http://download.oracle.com/javase/6/docs/api/java/util/Set.html#add%28E%29

0

精彩评论

暂无评论...
验证码 换一张
取 消