0

I created an Employee class and overridden the hashCode and equals methods. Now I use this class as key in HashMap creation. Until the keys are not modified everything works fine, but as soon as I start playing with keys and try to view the HashMap contents, its output confuses me. When I iterate the HashMap, it retains the key which was already overridden by myself in earlier steps. So e1, e2 and e3 are 3 key objects. i modify e1 to point to new fresh object(name=hrithik, id=123) and thus map.get method returns null which is fine. now i assign e2(name=sachin,id=456) to e1 and thus e1's old content should be lost(name=sachin,id=123). Now problem starts here. When i iterate the hashmap, i see the e1 key contents still pointing to old reference(name=sachin,id=123) instead of (name=sachin,id=456). What is the reason behind it?

Employee class

package hashmapConfusion;

public class Employee {

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getEmpId() {
        return empId;
    }

    public void setEmpId(int empId) {
        this.empId = empId;
    }

    private String name;
    private int empId;

    Employee(String name, int empId){
        this.name = name;
        this.empId = empId;
    }

    @Override
    public int hashCode() {
        return 31*(name.length())*(name.charAt(0));
    }

    @Override
    public boolean equals(Object o) {
        if(!(o instanceof Employee)) {
            return false;
        }else {
            Employee an = (Employee) o;
            if(this.name.equals(an.name) && this.empId==an.empId) {
                return true;
            }
        }
        return false;
    }
}

Test class for HashMap

package hashmapConfusion;

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

public class AddEmployeeHashMap {

    public static void main(String[] args) {

        Map<Employee, String> map = new HashMap<Employee, String>();
        Employee e1 = new Employee("sachin",123);
        Employee e2 = new Employee("sachin",456);
        Employee e3 = new Employee("sachin",456);
        map.put(e1, "lo");
        map.put(e2, "lo another");
        map.put(e3, "lo another another");
        /*map.put(e2, "value");
        map.put(e3, "value3");*/
        /*e3 = new Employee("sachin",456);*/
        System.out.println(map.get(e1));
        e1= new Employee("hrithik",123);
        System.out.println(map.get(e1));
        e1=e2;
        System.out.println("value 1"+map.get(e1));
        System.out.println("value 2"+map.get(e2));
        for(Map.Entry<Employee, String> obj:map.entrySet()) {
            System.out.println("AFTER ONE KEY CHANGE");
            System.out.println(obj.getKey()+"="+obj.getValue());
        }
        for(Employee obj:map.keySet()) {
            System.out.println("key values");
            System.out.println(obj.getName()+"="+obj.getEmpId());
        }
        e2.setEmpId(300);
        System.out.println("size after change both keys-"+map.size());
        for(Entry<Employee, String> obj:map.entrySet()) {
            System.out.println();
            System.out.println(obj.getKey()+"="+obj.getValue());
        }
        System.out.println(map.size());
        /*map.forEach((key, val)->{
            Employee e4 = new Employee("sachin",456);
            System.out.println(val+"-");
            if(key.equals(e4))
                System.out.println("found val-"+val);
        });*/

    }

}

And the output

lo
null
value 1lo another another
value 2lo another another
AFTER ONE KEY CHANGE
//WHY DOES IT PRINT LO WHEN KEY HAS ALREADY BEEN CHANGED FROM E1 TO E2
hashmapConfusion.Employee@538e=lo
AFTER ONE KEY CHANGE
hashmapConfusion.Employee@538e=lo another another
key values
//WHY IT IS SPITTING THE OLD KEY VALUES WHICH ARE WAY BACK OVERRRIDDEN
sachin=123
key values
sachin=456
size after change both keys-2
hashmapConfusion.Employee@538e=lo
hashmapConfusion.Employee@538e=lo another another
2
  • You should synchronize your hashmap – Maia Jan 25 '18 at 13:37
  • 1
    @Maia No, this is the classic problem of having mutable objects and thus a mutable hashcode/equality. – Mark Rotteveel Jan 25 '18 at 13:38
  • 1
    @MarkRotteveel race you to 50,000? – Kayaman Jan 25 '18 at 13:39
  • thanks for the comments . I will definitely keep that in mind. this is my first question on stackoverflow and will keep on learning from here on. – user1600902 Jan 25 '18 at 13:39
  • @user1600902 it's ok, is a common mistake when learning about maps (rather than `HashMap` only) and mutable keys (that you must avoid at all) – Luiggi Mendoza Jan 25 '18 at 13:41
  • i am not able to understand the output of iteration where even the first key is modified and points to reference of second key, still during hashmap iteration, it spits out the contents of initial key which should have been lost – user1600902 Jan 25 '18 at 13:45
  • That's not related to hashmaps, `e1=e2;` doesn't affect what you've put in the map, and you only (try to) modify `e2` which was overwritten in the map when `e3` was put in. I think your test code is going to confuse you only more because you're mixing so many different things in it. – Kayaman Jan 25 '18 at 13:52
  • i have added some more info for this. can you please explain me in little detail with each step explained , pardon my ignorance on this. – user1600902 Jan 25 '18 at 13:58
  • @MarkRotteveel you´re right – Maia Jan 25 '18 at 14:00
  • Go find an existing question that deals with `HashMap` internal details if you're interested. I'm not going to tutor you step by step on something that you shouldn't be doing anyway. – Kayaman Jan 25 '18 at 14:07
  • 1
    @Kayaman ;) I think you're going faster at the moment. – Mark Rotteveel Jan 25 '18 at 14:16

0 Answers0