Noorus Khan
Noorus Khan

Reputation: 1476

Custom object as Map key

AS I have read that if custom objects need to be the key of map, hashcode and equals method need to override, but in my case its working without overriding it. Could someone please tell whats getting wrong ?

    Map<Student,Integer> map = new HashMap<>();
    Student s1=new Student(1,"A");
    Student s2=new Student(2,"B");
    Student s3=new Student(3,"C");

    map.put(s1,1);
    map.put(s2,2);
    map.put(s1,3);

    for(Student s:map.keySet()) {
        System.out.println(map.get(s) + "->" + s.id + " " +s.name);
    }

Proper output:

3-> 1 A

2-> 2 B

Upvotes: 1

Views: 2958

Answers (3)

biziclop
biziclop

Reputation: 49724

Built-in hashCode() and equals() works fine. They're consistent in the way required by HashMap (i.e.: if hashCode()s aren't identical, equals() will always return false). That's because every object instance will only be equal() to itself.

However this is often not what you want it to do. Specifically, without overriding these methods, two instances of Student with identical fields will not be considered equal. So this will print out three lines instead of one:

Map<Student,Integer> map = new HashMap<>();
Student s1=new Student(1,"A");
Student s2=new Student(1,"A");
Student s3=new Student(1,"A");

map.put(s1,1);
map.put(s2,2);
map.put(s3,3);

for(Student s:map.keySet()) {
    System.out.println(map.get(s) + "->" + s.id + " " +s.name);
}

(Note: technically this is all perfectly correct, but is not necessarily what most people reading your code would expect to happen.)

Upvotes: 4

Anton Balaniuc
Anton Balaniuc

Reputation: 11739

It is one of the properties of equals method: it is reflexive. Which means that

x.equals(x) == true 

An object is always equal to itself. In this case you are relaying on default implementation of equals method.

map.put(s1,1); 
map.put(s1,3);

and because the default implementation is reflexive

s1.equals(s1) == true 

value 1 is replaced with 3

However result will be different if you will do something like this

map.put(new Student(1,"A"),3);

s1.equals(new Student(1,"A")); 

You will need to override hashCode and equals to make it work properly.

Upvotes: 6

Abrikot
Abrikot

Reputation: 995

If there is no overriding hashCode nor equals method, Java compares object references. Thus, s1 reference is the same as s1 reference, so you can replace s1 associated value with another.

If you create a new Student object with the same attributes values than s1, and try to insert it into your map, you'll have two different pairs.

Upvotes: 3

Related Questions