0
package com.sample;

import java.util.HashMap;

class Student{
    int id;

    @Override
    public int hashCode() {
        return -1;
    }

    @Override
    public boolean equals(Object obj) {
        return false; // returning false
    }

}

public class MainClass {

    public static void main(String[] args) {
        Student s1=new Student();
        s1.id=123;
        Student s2=new Student();
        s2.id=456;

        HashMap<Student,String> s=new HashMap<Student,String>();


        s.put(s1, "One");
        System.out.println(" < s1 value > "+s.get(s1) + " < s1 hashcode > "+s.get(s1).hashCode());
        s.put(s2, "Two");
        System.out.println(" < s2 value > "+s.get(s2) + " < s2 hashcode > "+s.get(s2).hashCode());
        s.put(s1, "Three");
        System.out.println(" < s1 value > "+s.get(s1) + " < s1 hashcode > "+s.get(s1).hashCode());

        System.out.println("after insert");

        System.out.println(" < s1 value > "+s.get(s1) + " < s1 hashcode > "+s.get(s1).hashCode());
        System.out.println(" < s2 value > "+s.get(s2) + " < s2 hashcode > "+s.get(s2).hashCode());


    }

}



OUTPUT

 < s1 value > One < s1 hashcode > 79430
 < s2 value > Two < s2 hashcode > 84524
 < s1 value > Three < s1 hashcode > 80786814
after insert
 < s1 value > Three < s1 hashcode > 80786814 //printing three for s1
 < s2 value > Two < s2 hashcode > 84524 //printing two for s2

// Now if we change the return type of equals method to true , output changes and both returns three as output. I am unable to understand why the output changes if we are changing the return type of equals method. Please explain with the context of bucket(HashMap) and equals method.

class Student{
    int id;

    @Override
    public int hashCode() {
        return -1;
    }

    @Override
    public boolean equals(Object obj) {
        return true; //returning true
    }

}

public class MainClass {

    public static void main(String[] args) {
        Student s1=new Student();
        s1.id=123;
        Student s2=new Student();
        s2.id=456;

        HashMap<Student,String> s=new HashMap<Student,String>();


        s.put(s1, "One");
        System.out.println(" < s1 value > "+s.get(s1) + " < s1 hashcode > "+s.get(s1).hashCode());
        s.put(s2, "Two");
        System.out.println(" < s2 value > "+s.get(s2) + " < s2 hashcode > "+s.get(s2).hashCode());
        s.put(s1, "Three");
        System.out.println(" < s1 value > "+s.get(s1) + " < s1 hashcode > "+s.get(s1).hashCode());

        System.out.println("after insert");

        System.out.println(" < s1 value > "+s.get(s1) + " < s1 hashcode > "+s.get(s1).hashCode());
        System.out.println(" < s2 value > "+s.get(s2) + " < s2 hashcode > "+s.get(s2).hashCode());


    }

}


OUTPUT-

 < s1 value > One < s1 hashcode > 79430
 < s2 value > Two < s2 hashcode > 84524
 < s1 value > Three < s1 hashcode > 80786814
after insert
 < s1 value > Three < s1 hashcode > 80786814 //printing three for s1
 < s2 value > Three < s2 hashcode > 80786814 //printing three for s2
Saurabh Prakash
  • 2,715
  • 1
  • 11
  • 17
  • Please refer to [Why map uses equals method for checking keys](http://stackoverflow.com/questions/31860486/does-a-map-using-equals-method-for-key-checking-exists) – Sourav Purakayastha Feb 09 '17 at 13:33

1 Answers1

3

In your first snippet, your equals method always returns false, which means the HashMap considers all Student instances to be unique. Therefore s.get(s1) and s.get(s2) return different values.

In your second snippet, your equals method always returns true and your hashCode always returns -1, which means the HashMap considers all Student instances to be the same. Therefore s.get(s1) and s.get(s2) both return the same value (each call to put overrides the previous value). The value is "Three", since that's the last value you put in the Map (by calling s.put(s1, "Three");).

P.S., printing s.get(s1).hashCode() seems pointless, since it's the hashCode of the key (s1.hashCode()) that determines the bucket in which the entry will be stored in the HashMap, not the hashCode of the value.

BTW, I was initially surprised that your first snippet doesn't return null in all calls to s.get(), since equals always returns false, so the HashMap shouldn't be able to locate a key which is equal to the given key. However, checking the source code of HashMap I found that the keys are first compared with == before equals is called, which is why the HashMap could locate your keys.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • Hi Eran, I have a doubt, in first snippet,when the equals method is returning false. firstly,when we are doing,s.put(s1, "One"),this will store the value in the HashMap but again when we are doing s.put(s1, "Three"),why this is replacing the value and not throwing exception ? – Saurabh Prakash Feb 09 '17 at 20:34
  • According to my understanding,when we are using,s.put(s1, "Three"), it will perform hashing on the key and get the bucket index and stores the value at that index. Now when we are doing s.put(s1, "Three") , it will perform hasing on the key and get the bucket index,it will compare the key with the entry at that index , then it will always return false as equals method is overridden to return false everytime. So it should have one more entry, but having one more entry with the same key will violate the hashmap properties , thats why it should return an error . – Saurabh Prakash Feb 09 '17 at 20:34