Reputation: 23
I'm doing a school assignment where I need to store a bunch of contacts. Each contact has a HashSet
of social network accounts, addresses and phone numbers.
I DO NOT want to store multiple copies of the same object in my HashSet
, so I have overridden the hashCode()
and equals()
method for each object.
But for my social network account object only,my HashSet
is storing the same object twice!
I have two different objects:
SocialNetworkAccount s1 = new SocialNetworkAccount(SocialNetworkAccount.AccountType.FACEBOOK, "wallcrawler123");
SocialNetworkAccount s2 = new SocialNetworkAccount(SocialNetworkAccount.AccountType.FACEBOOK, "wallcrawler123");
s1.equals(s2)
returns true
and s1.hashCode() == s2.hashCode()
returns true
, but s1 == s2
returns false
! Why?
This is the hashCode()
method I'm using:
public int hashCode() {
int prime = 31;
int result = 1;
result = result*prime + type.hashCode();
result = result*prime + id.hashCode();
return result;
}
Upvotes: 1
Views: 2881
Reputation: 7459
maybe you have done somthing like this?
SocialNetworkAccount s1 = new SocialNetworkAccount(SocialNetworkAccount.AccountType.FACEBOOK, "foo");
SocialNetworkAccount s2 = new SocialNetworkAccount(SocialNetworkAccount.AccountType.FACEBOOK, "bar");
hashSet.add(s1);
hashSet.add(s2);
s2.setNickname("foo");
System.out.println(s1.equals(s2)); // true
System.out.println(hashSet); // [FACEBOOK:foo, FACEBOOK:foo]
Upvotes: 1
Reputation: 178263
I suspect that the problem is that your equals
method is not overriding Object
's equals
method, which takes an Object
as a parameter.
I suspect that your equals
method takes a parameter of SocialNetworkAccount
, not Object
. I can't know for sure because you haven't posted your equals
method, but it is a possible explanation. In this case, the equals
method in Object
is not overridden, so when HashSet
(eventually) calls it, it calls Object
's equals
method, which compares references to see if they are the same.
If so, modify your equals
method to accept an Object
instead of a SocialNetworkAccount
, so it overrides equals
properly.
Also, using the @Override
annotation will catch when a method that intends to override another method in fact does not override it.
Upvotes: 2
Reputation: 17707
hashCode method is used to coarsly assign entries to the table, but the equals(...) method has to return true for the two instances to be treated as identical.
Since you don't show us the equals method I assume you have not created your own version, which means the HashTable is useing the default implementation, which does a == b
and your two instances are not the same instance, so that returns false, hence two entries in the table.
What you need to do is implement the equals method too:
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof SocialNetworkAccount) {
SocialNetworkAccount their = (SocialNetworkAccount)o;
return xxx.equals(their.xxx ) && yyy.equals(their.yyy) && ...;
}
return false;
}
Replace xxx and yyy and so on with the values in your class.
See the hashCode and equals contract
Upvotes: 1
Reputation: 3185
The == operator compares references. Since there are two different objects, their references will be different.
SocialNetworkAccount s1 = new SocialNetworkAccount(SocialNetworkAccount.AccountType.FACEBOOK, "wallcrawler123");
SocialNetworkAccount s2 = s1;
if (s1 == s2) {
System.out.println("The references are the same.");
}
Upvotes: 2