问题
This question already has an answer here:
- When does HashSet 'add' method calls equals? [duplicate] 4 answers
Please clarify my doubt in Hashset. Consider the following code,
class Person
{
String name;
Person(String n)
{
name=n;
}
public String getName()
{
return name;
}
@Override
public boolean equals(Object arg0) {
System.out.println(\"in equals\");
Person obj=(Person)arg0;
System.out.println(\"1st \"+getName());
System.out.println(\"2nd \"+obj.getName());
if(this.getName().equals(obj.getName()))
{
return true;
}
return false;
}
@Override
public int hashCode() {
System.out.println(\"in hash code\");
System.out.println(\" value is \"+Integer.valueOf(name.charAt(0)));
return Integer.valueOf(name.charAt(0));
}
}
in main I have the following code
Person obj1=new Person(\"bcd\");
Person obj2=new Person(\"cde\");
Person obj3=new Person(\"abc\");
Person obj4=new Person(\"abc\");
Now if I add these objects to hashset
Set<Person> sset=new HashSet<Person>();
sset.add(obj1);
sset.add(obj4);
sset.add(obj2);
sset.add(obj3);
I am getting this output
in hash code
value is 98
in hash code
value is 97
in hash code
value is 99
in hash code
value is 97
in equals
1st abc
2nd abc
Question 1 : why equals() function is called only once for checking obj3 and obj4 ? Why its not checked for rest of the objects ?
Question 2 : If the answer is because they both have same hash code,only then equals will be called, then why its not called for below code
sset.add(obj1);
sset.add(obj4);
sset.add(obj2);
sset.add(obj4);
output is :
in hash code
value is 98
in hash code
value is 97
in hash code
value is 99
in hash code
value is 97
It\'s not going inside equals() method even though two same objects are added to hash set which has same hash code.
Question 3 :I iterated the above value and printed the contents but neither hashcode nor equals were called. when its really useful to override hashcode and equals method ?
Question 4 : When will hashCode()
and equals()
be called?
回答1:
- There's no need to call
equals
ifhashCode
differs. - There's no need to call
hashCode
if(obj1 == obj2)
. - There's no need for
hashCode
and/orequals
just to iterate - you're not comparing objects - When needed to distinguish in between objects.
回答2:
I think your questions will all be answered if you understand how Sets, and in particular HashSets work. A set is a collection of unique objects, with Java defining uniqueness in that it doesn't equal anything else (equals returns false).
The HashSet takes advantage of hashcodes to speed things up. It assumes that two objects that equal eachother will have the same hash code. However it does not assume that two objects with the same hash code mean they are equal. This is why when it detects a colliding hash code, it only compares with other objects (in your case one) in the set with the same hash code.
回答3:
according jdk source code from javasourcecode.org, HashSet use HashMap as its inside implementation, the code about put method of HashSet is below :
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
The rule is firstly check the hash, then check the reference and then call equals method of the object will be putted in.
回答4:
Because in 2nd case you adding same reference twice and HashSet
have check against this in HashMap.put()
on which HashSet
is based:
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
As you can see, equals
will be called only if hash of key being added equals to the key already present in set and references of these two are different.
回答5:
You should read up on how to ensure that you've implemented equals and hashCode properly. This is a good starting point: What issues should be considered when overriding equals and hashCode in Java?
回答6:
Please debug HashSet with all its methods and you will see how it works
来源:https://stackoverflow.com/questions/5396939/hashcode-and-equals-for-hashset