Win a copy of Functional Reactive Programming this week in the Other Languages forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Do I have to override equals() due to using an object as a hashmap key? Yes..but..

 
Faber Siagian
Ranch Hand
Posts: 52
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
K&B tells that HashMap key has to override the equals() properly so that it can be found
in the Collection.

Look at the following code :



Unfortunately the result of the program is null. I can't found the person whose name is Faber and age is 22, though the equals() is overridden.
Is there any mistake in the program?
 
Ireneusz Kordal
Ranch Hand
Posts: 423
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

you use HashMap as your map, so you must override hashCode() method in class Person too. Your overriden hashCode method must return the same value for objects (persons) for which equals method returns true.
HasMap searches keys using hashcodes. Because hasCode() is not overriden, the hashCode from Object class is used, and this 'version' of hashCode always returns different valuse for each new object.
In this line:
you create one object, and in this line:
you create second object - these two objects are different, so default hashCode method returns different valuses for each one, and therefore map cannot locate the second object and returns null.
The simpliest hashCode() method for your class might be:


[ July 20, 2008: Message edited by: Ireneusz Kordal ]
[ July 20, 2008: Message edited by: Ireneusz Kordal ]
 
Faber Siagian
Ranch Hand
Posts: 52
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've tried to override the hashcode(). But the result is still the same.
Somebody explain to me bout the problem.
 
Sunny Mattas
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,
I think lot depends on the way you have implemented the hashcode method.It should return same hash code for multiple calls from objects,those you want to pass the equality test in your code.

Regards
Sunny
 
Dawn Charangat
Ranch Hand
Posts: 249
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Its not the hashCode() that might be causing your problem. In a hashmap, a particular value can be got by get() only if the key supplied passes the map.containsKey(key) method call. Internally, the containsKey() method invokes a original_key.equals(supplied_key) check. In your case, since you are always creating a "new" instance of 'Person' object while put() & get() operations, the equals() method fails (returns false), and hence the problem. Had you used the same reference while get() & put(), your program would have worked fine.

The below code works just fine :

public static void main(String[] args)
{
Map<Person, String> map = Collections.checkedMap(new HashMap<Person, String>(), Person.class, String.class);

Person person = new Person("Faber", 22);

map.put(person, "Faber-22");
map.put(new Person("LeBron James", 23), "LeBron James-23");
map.put(new Person("Del Piero", 31), "Del Piero-31");

System.out.println(map.get(person));
}
 
Sunny Mattas
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,
I think lot depends on the way you have implemented the hashcode method.It should return same hash code for multiple calls from objects,those you want to pass the equality test in your code.

Regards
Sunny
 
Sunny Mattas
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi,

But here in code equals method is implemented and there is no "==" for comparing two reference. In equals method we are checking instanceOf and one of variable values for two objects.
If two references were compared using "==" in equals then keys created using new would not pass equality test

Please correct me if I am wrong

Regards
Sunny Mattas
 
Dawn Charangat
Ranch Hand
Posts: 249
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Sunny (and others),

You are perfectly correct in what you say... but then there is a slight difference in the way containsKey() method works in a HashMap. You've over-ridden an equals() method, and rightly so.., but if you happen to take a look at how the containsKey() infact in implemented in JDK :

public boolean containsKey(Object key) {
Object k = maskNull(key);
int hash = hash(k);
int i = indexFor(hash, table.length);
Entry e = table[i];
while (e != null) {
if (e.hash == hash && eq(k, e.key))
return true;
e = e.next;
}
return false;
}

It checks not just for the contents to be equal, but also their hash values - which just have not been equal in our current case. Hope this clears atleast some clouds.

regards,
Dawn.
 
Sunny Mattas
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[B][/B]

Hi Dawn
So it means if we try to find a object in hashmap using keys, then containsKey() method is called.Here in containsKey() method hash value of sent key is found and other key with same hash value is retrieved .
Now the equals method is called to compare values of Keys. If values are same then true is returned and our search finishes, otherwise continues.
Where is the test for comparing references? I don't think any such condition exists.
Kindly inform me if i have understood something wrong.

Regards
Sunny
 
Raphael Rabadan
Ranch Hand
Posts: 141
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Faber,

While using the .get() in a Hash like HashMap, HashTable, HashSet, LinketHashSet and all others that uses Hash, its mandatory to override the hashCode() and the equals().

When we use .get() it will 1st check the hashCode of the object will take a look if it already exists, if not, it will stop there, thats why you are getting the null, if you don't override hashCode() for each new XXXX(), in your case, new Person() will bring a diferent hashCode, meaning, for the Hash, diferent objects.

Study the contract between hashCode and equals and you'll be ok.

Take a look at this two examples and see if any doubt remains:



and



Kind Regards,
Raphael Rabadan
[ July 23, 2008: Message edited by: Raphael Rabadan ]
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic