GeeCON Prague 2014*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes HashMap and equals method overriding Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "HashMap and equals method overriding" Watch "HashMap and equals method overriding" New topic
Author

HashMap and equals method overriding

Naseem Khan
Ranch Hand

Joined: Apr 25, 2005
Posts: 809
Hi ranchers,
I am facing one problem in retrieving the objects stored in HashMap. It retrurns null. I am overriding equals() method in Car class.

Following code stores (CarObj, OwnerString) as a (key,value) pair in HashMap.I want the name of the owner of some car.



Following line returns true. But map returns null. If both car insances are same, then it must return same owner.



With String it works fine. Is there any other method of Object class I have to override in my case like hashCode().


Thanks & Regards

Naseem
[ May 17, 2006: Message edited by: Naseem Khan ]

Asking Smart Questions FAQ - How To Put Your Code In Code Tags
Christophe Verré
Sheriff

Joined: Nov 24, 2005
Posts: 14688
    
  16

The two instances are not the same. There content is equal, but there reference is different.
Mr Burns's car1000, "Mercedes Benz")
Barney's car1000, "Mercedes Benz")

Same brand, same weight, but there are still two different cars.
[ May 17, 2006: Message edited by: Satou kurinosuke ]

[My Blog]
All roads lead to JavaRanch
Naseem Khan
Ranch Hand

Joined: Apr 25, 2005
Posts: 809

Quote from Satou kurinosuke

The two instances are not the same. There content is equal, but there reference is different.
Mr Burns's car 1000, "Mercedes Benz")
Barney's car 1000, "Mercedes Benz")

Same brand, same weight, but there are still two different cars.





U mean to say that if u don't have ny handle or reference of ur key object (of some custome class like Car), then u will get null frm Map.

Wat about String

Using String as a key, even If u create a new String by new String("") map gets the value. In that case also String content is same not references.




Wat extra String class has


Thanks

Naseem.K

[ May 17, 2006: Message edited by: Naseem Khan ]

[ May 17, 2006: Message edited by: Naseem Khan ]
[ May 17, 2006: Message edited by: Naseem Khan ]
wise owen
Ranch Hand

Joined: Feb 02, 2006
Posts: 2023
HashMap clearly states that it implements the Map interface. The Map interface clearly states that it uses .equals(Object) for object comparison.
HashMap key comparison use equals()
Naseem Khan
Ranch Hand

Joined: Apr 25, 2005
Posts: 809
If .equals(Object) method is invoked to determine key equality, my equals method returns true.

In K&B book its mentioned that...

1. If .equals(Object) method returns true, then two Objects are same. Same means their contents are same.

2. If == returns true, then two references are same.

Thanks

Naseem
[ May 17, 2006: Message edited by: Naseem Khan ]
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18876
    
  40

HashMap also uses the hashcode() method to store the object, if the hashcode is different, then it will be stored incorrectly.

Add this to your Car class...



Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Firas Zuriekat
Ranch Hand

Joined: May 09, 2006
Posts: 144
I am facing one problem in retrieving the objects stored in HashMap. It retrurns null. I am overriding equals() method in Car class


But you don't have objects really stored! You only have one object stored. So that's why the second object's value is null.

The following works because it has both objects stored:

import java.util.HashMap;
import java.util.Map;

class Car {
private int weight;
private String CarName;
public Car(int weight, String CarName){
this.weight=weight;
this.CarName=CarName;
}

public boolean equals(Object obj) {
Car carObj=null;
if(obj instanceof Car){
carObj=(Car)obj;
}
if(carObj!=null && (this.weight==carObj.weight) && (this.CarName.equals(carObj.CarName))){
return true;
}return false;

}

public static void main(String[] args) {

Map map=new HashMap();
Car myCar=new Car(1000, "Mercedes Benz");
map.put(myCar, "Naseem");
Car neighborCar=new Car(1000, "Mercedes Benz");
map.put(neighborCar, "Naseem's Neighbor");
System.out.println(neighborCar.equals(myCar)); //Line 1
System.out.println(map.get(neighborCar)); //Line 2
}}
[ May 17, 2006: Message edited by: Firas Zureikat ]
vivekkumar sharma
Ranch Hand

Joined: Dec 21, 2005
Posts: 70
HI
for Maps remember bucket concept.
when you put any thing into a Map, first its hashcode is looked at to calcualte in which bucket objects shall go.

and in case of reading a map reverse process is followed.First hascode is looked to find bucket and then inside bucket objects ar compared using equals method to find correct object.

ypu have not not overridden hashcode method.Thats why u are not able to retrive correct object,because program does not find correct bucket.
Naseem Khan
Ranch Hand

Joined: Apr 25, 2005
Posts: 809

Quote from Henry Wong

HashMap also uses the hashcode() method to store the object, if the hashcode is different, then it will be stored incorrectly.

Add this to your Car class...


code:
--------------------------------------------------------------------------------

public int hashCode() { return weight + CarName.hashCode(); }

----------------------------------------------------------------------------






Its really a very gud point u have made. With hashCode implementaion which u have mentioned, map returns ownerName.


String str1=new String("First");
String str2=new String("First");

1. .equals(Object) checks content. It returns true. Fine>>>
2. == operator checks references. Different returns false. Fine>>>
3 boolean b=(str1.hashCode()==str2.hashCode());
here b is set to true.

Wat exactly hashCode() signifies... it returns some int value>>-5647865


Thanks & Regards

Naseem Khan
[ May 17, 2006: Message edited by: Naseem Khan ]
Firas Zuriekat
Ranch Hand

Joined: May 09, 2006
Posts: 144
Sorry I misunderstood the question in my above reply. Actually, you want to use another equivalent key, "myCar", as a key to retrieve the value associated with key "neighborCar". I just mean you want "myCar" to be equal to "neigborCar".

The hashcode calculation for the buckets should be close to that of the equals method (at least as complex).

Since carWeight and carName were tied together in an "&&", then any of these will work:

1) public int hashCode() { return weight * CarName.hashCode(); }
2) public int hashCode() { return weight + CarName.hashCode(); }
3) public int hashCode() { return weight - CarName.hashCode(); }
4) public int hashCode() { return weight / CarName.hashCode(); }

Equals method used 2 things (variables), so hashcode above uses 2 things. The hashcode should be at least as complex as equals to have meaningful equality between objects.
[ May 17, 2006: Message edited by: Firas Zureikat ]
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18876
    
  40

Wat exactly hashCode() signifies... it returns some int value>>-5647865


A hashcode is a single number that represents the object. The hashmap uses it to determine which "bucket" to place the item. Ideally, you want a hashcode formula that gives you as even distribution as possible, so that the hashmap can be used as efficiently as possible.

Doesn't really matter though, as the hashmap will still work, if say, the hashcode that is returned is always zero -- just not very efficient.


In your example, the hashcode return is based on the Object class, which is based on the reference value -- which means that the two cars had different hashcodes. For a hashmap, equal keys must have equal hashcodes, or they will be placed/search in different buckets.

Henry
Naseem Khan
Ranch Hand

Joined: Apr 25, 2005
Posts: 809
Thanks to all...

Actually there is a joint contract betwen
equals(Object) and hashCode().Both works together.

If two objects are considered equal using .equals(Object) method, then they must have same hashCode value which was not in my case.

regards

Naseem.K
Sreeraj Harilal
Ranch Hand

Joined: May 09, 2006
Posts: 45
import java.util.HashMap;
import java.util.Map;
class Car {
private int weight;
private String CarName;

public Car(int weight, String CarName){
this.weight=weight;
this.CarName=CarName;
}

public boolean equals(Object obj) {
Car carObj=null;
if(obj instanceof Car){
carObj=(Car)obj;
}
if(carObj!=null && (this.weight==carObj.weight) &&
(this.CarName.equals(carObj.CarName))){
return true;
}
return false;
}

public int hashCode()
{
return 1;
}


public static void main(String[] args) {

Map map=new HashMap();

Car myCar=new Car(1000, "Mercedes Benz");

map.put(myCar, "Naseem");

Car neighborCar=new Car(1000, "Mercedes Benz");

System.out.println(neighborCar.equals(myCar)); //Line 1

System.out.println(map.get(neighborCar)); //Line 2
}
}

Its work fine to ur needs.
Because if u r not override the hashcode method then it uses the Objects hashCode (default) method. Objects hashcode returns the address of the objects.U r created 2 new (using new operator) objects. So the address are different. Map checks hashCode first for comparison then it checks equals.
If hashCode is not equal its will not check the equals method.


SCJP 5.0<br />SCWCD 1.4<br />SCBCD 1.3<br />SCEA part 1
Naseem Khan
Ranch Hand

Joined: Apr 25, 2005
Posts: 809

public int hashCode()
{
return 1;
}


returning hashCode() value as 1 is not a very gud design becoz in this case, all the objects will land in the same bucket and in that case whole searching operation must be performed by .equals(Object) method.
In Short, Map is not efficient in searching.

Implement hashCode() in such a way that all objects land in different buckets would be a gud design in terms of efficiency of the Map.

Thanks

Naseem.K
Sreeraj Harilal
Ranch Hand

Joined: May 09, 2006
Posts: 45
Yes u r right.I agree with u.
 
GeeCON Prague 2014
 
subject: HashMap and equals method overriding