quintin
quintin

Reputation: 837

Why it is necessary to override equals when I am overriding hashcode and getting values from hashmap

public class DemoHashSet {
private String name;
private String dob;
private String gender;

public DemoHashSet(String name, String dob, String gender) {
    super();
    this.name = name;
    this.dob = dob;
    this.gender = gender;
}

public String getName() {
    return name;
}

public String getDob() {
    return dob;
}

public String getGender() {
    return gender;
}

@Override
public String toString() {
    return name+" "+dob+" "+gender;
}

@Override
public boolean equals(Object o) {
    return this.name.equals(((DemoHashSet)o).getName());
}

@Override
public int hashCode() {
    int code = this.name.hashCode() + this.dob.hashCode() + gender.hashCode();
    System.out.println("Hash Code: "+code);
    return code;
}

public static void main(String args[]) throws ParseException {

    Map<DemoHashSet, String> hmap = new HashMap<DemoHashSet, String>();

    DemoHashSet obj1 = new DemoHashSet("key1", "121990", "male");
    DemoHashSet obj2 = new DemoHashSet("key2", "122990", "male");
    DemoHashSet obj3 = new DemoHashSet("key3", "123990", "male");
    DemoHashSet obj4 = new DemoHashSet("key4", "124990", "male");
    DemoHashSet obj5 = new DemoHashSet("key5", "125990", "male");

    hmap.put(obj1, "value1");
    hmap.put(obj2, "value2");
    hmap.put(obj3, "value3");
    hmap.put(obj4, "value4");
    hmap.put(obj5, "value5");

    System.out.println("Get values: ");
    System.out.println(hmap.get(new DemoHashSet("key1", "121990", "male")));
    System.out.println(hmap.get(new DemoHashSet("key2", "122990", "male")));
}
}

In this code I am overriding hashcode() and equals() function

when I run this code i get following output:

Hash Code: 1457153183
Hash Code: 1457182975
Hash Code: 1457212767
Hash Code: 1457242559
Hash Code: 1457272351
Get values: 
Hash Code: 1457153183
value1
Hash Code: 1457182975
value2

when I override only hashCode() function and comment equlas() method I get following output:

Hash Code: 1457153183
Hash Code: 1457182975
Hash Code: 1457212767
Hash Code: 1457242559
Hash Code: 1457272351
Get values: 
Hash Code: 1457153183
null
Hash Code: 1457182975
null

Need explanation for this behaviour as the hash code computed in both scenarios is same but it gives null in 2nd case.

Upvotes: 0

Views: 250

Answers (4)

Ankit Sharma
Ankit Sharma

Reputation: 1565

Need explanation for this behaviour as the hash code computed in both scenarios is same but it gives null in 2nd case.

It all related to how hashmap's get methods works internally. When you call get method of a hashmap for a specified key, Internally this key's hashcode method gets called to calculate bucket location. Once it gets bucket location, it calls equals method of specified key to compare with existing objects inside that bucket (actually class Entry objects) and if any object is equal to specified object according to equals method, it returns that object.

case 1 : I am overriding hashcode() and equals() methods

hmap.get(new DemoHashSet("key1", "121990", "male")) hmap.get(new DemoHashSet("key2", "122990", "male"))

according to your equals method implementation, two DemoHashSet objects are equal if they have same name. Thats why you are getting results in this case.

case 2 : I override only hashCode() function and comment equlas() method

hmap.get(new DemoHashSet("key1", "121990", "male")) hmap.get(new DemoHashSet("key2", "122990", "male"))

In this case, no custom equals method implementation available, so it will take default implementation and according to default implementation - two objects are same if and only if their references are same. So new DemoHashSet("key1", "121990", "male") and new DemoHashSet("key1", "121990", "male") are not same even they are carrying same values. So hashmap is not getting those objects in that bucket. That's why you are getting null.

For more info: http://javarevisited.blogspot.in/2011/02/how-hashmap-works-in-java.html

Upvotes: 2

Saif
Saif

Reputation: 7042

Need explanation for this behavior
This is the exact expected behavior i should expect. why?
There is one thing about hascode and that is you can't give 100% assurance of uniqueness for unique object. That means in some cases different object can have similar hascode.

And HashMap implementation kept that in mind. so when you pass a key they always compare the hascode and then check equality (reference check then the equals() method ). if nothing found return null. you can check the source code:

if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))

This code block says:

  • hash (hascode) need to be same for both given key and entry key

AND

  • given key and entry key need to be same object (same reference ) OR they need to be equal by the equals() method

In you case when you comment the equals method the default implementation of equals() method form the super class is used, which actually check the reference equality only I guess. so

DemoHashSet obj1 = new DemoHashSet("key1", "121990", "male");

and later

 new DemoHashSet("key1", "121990", "male") //ins hmap.get()

doesn't refer to the same object so equals() return false and get() return null as no match found for the key.
When your equals() method exist according to your implementation you are telling those object are equal as they have same name.

hashcode cannot assure and is not Equality.

Upvotes: 2

Charles Spencer
Charles Spencer

Reputation: 647

You are using a HashMap. Internally, HashMap's have a number of buckets, each of which has a list of the items you are storing.

Whenever you call HashMap.get(), the HashMap will call DemoHashSet.hashCode() and use the key argument, possibly with the modulus (%) operator, to figure out which bucket to look in.

Then, it will search through this list using the DemoHashSet.equals() method to see if it can match the key argument. If it equals() ever returns true, then the value will be returned, otherwise null.

From the documentation for Object.equals():

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

Upvotes: 1

Ravindra babu
Ravindra babu

Reputation: 38910

hadCode() function has meant for storing the object in a specific segment/bucket by deriving the key of object to specific segment/bucket. To understand the purpose of this method, you need to know how HashTable or HashMap works internally. Wikipedia is the best source to understand about it.

equals() function has meant for checking the existence of particular Object in the collection object.

If two objects are equal, the hasCode will be same but converse is not true. Two different objects can have same hashCode

Upvotes: 0

Related Questions