wood burning stoves*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Do I have to override equals() due to using an object as a hashmap key? Yes..but.. Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Do I have to override equals() due to using an object as a hashmap key? Yes..but.." Watch "Do I have to override equals() due to using an object as a hashmap key? Yes..but.." New topic
Author

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

Faber Siagian
Ranch Hand

Joined: Jul 08, 2008
Posts: 52
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?


Sun Certified Programmer for the Java 2 Platform, Standard Edition 5.0 (88 %)
Ireneusz Kordal
Ranch Hand

Joined: Jun 21, 2008
Posts: 423
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

Joined: Jul 08, 2008
Posts: 52
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

Joined: Apr 22, 2008
Posts: 45
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


Regards
Sunny Mattas
SCJP5
Dawn Charangat
Ranch Hand

Joined: Apr 26, 2007
Posts: 249
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

Joined: Apr 22, 2008
Posts: 45
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

Joined: Apr 22, 2008
Posts: 45
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

Joined: Apr 26, 2007
Posts: 249
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

Joined: Apr 22, 2008
Posts: 45
[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

Joined: Jul 05, 2008
Posts: 141
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 ]

SCJP Java 6 (98%) - Story, SCJA (88%) - Story
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Do I have to override equals() due to using an object as a hashmap key? Yes..but..
 
Similar Threads
Confusion about HashCode
HashTable Problem
Comparator
HashCode and Equals
Getting custom key from map based on comparator etc.