0

i am trying to understand HashMap put behavior and i am bit confused about below scenario . below is implementation for one of the class which i am going to use as key in HashMap

class Person {
    int id;
    String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

}

for testing purpose i have a util method

public  void displayMap() {
        Person person = new Person();
        person.setId(1);
        person.setName("praveen");
        Map<Person, String> mapPerson = new HashMap<>();
        mapPerson.put(person, "");
        person.setId(2);
        person.setName("praveen");
        mapPerson.put(person, "");
        System.out.println(mapPerson);
    }

I expected output to be {Person [id=1, name=praveen]=, Person [id=2, name=praveen]=} but i see it as {Person [id=2, name=praveen]=, Person [id=2, name=praveen]=}.

I am using the same person object to insert multiple times as key but with different id values. but as far as my understanding if the key is same it should ideally replace the existing key with the new key. but what i see is person with Id=2 and name=praveen displaying multiple times. is that not duplication of key and violate the principle of hashmap with duplicate keys? and why is it display {Person [id=2, name=praveen]=, Person [id=2, name=praveen]=} not {Person [id=1, name=praveen]=, Person [id=2, name=praveen]=}

Praveen
  • 13
  • 3

1 Answers1

2

From the Map Javadoc:

Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.

The summary of that instruction: never, ever modify something you just put in as a map key, Bad Things will happen, and there's no way of telling what bad things will happen.

You modified something you put in as a map key, and bad things happened, basically.

You should be starting a new Person object for the second insertion, and then things will happen normally and correctly.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • you mean to say the behavior is not predicted in that case? i am curious why second put statement would change the key that has id =1 already – Praveen Jun 22 '17 at 00:01
  • You store a reference to the key, not the copy. In your entire program, there is only ever one Person object. – Louis Wasserman Jun 22 '17 at 00:02
  • Got it now. Thanks – Praveen Jun 22 '17 at 00:12
  • or, in other words, the same instance of Person is saved two times (different slots) in the map (one slot when saved with id=1, second slot when saved with id=2) – user85421 Jun 22 '17 at 00:13