Map lost my key!

Are you having trouble finding your keys in Maps?

Inspect the following code please..

First start with a model class:
package biz.tugay;
/* User: koray@tugay.biz Date: 18/12/15 Time: 21:01 */
 
public class Person {
 
    private String firstName;
    private String lastName;
 
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
 
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
 
        Person person = (Person) o;
 
        return firstName.equals(person.firstName)
                && lastName.equals(person.lastName);
    }
 
    @Override
    public int hashCode() {
        int result = firstName.hashCode();
        result = 31 * result + lastName.hashCode();
        return result;
    }
}

And then a Test Class with main method:
package biz.tugay;
/* User: koray@tugay.biz Date: 18/12/15 Time: 21:03 */
 
import java.util.HashMap;
import java.util.Map;
 
public class TestClass {
 
    public static void main(String[] args) {
        Map<Person, Integer> personIntegerMap = new HashMap<Person, Integer>();
        Person person = new Person();
        person.setFirstName("lray");
        person.setLastName("tugay");
        personIntegerMap.put(person, 2);
        person.setFirstName("kray");
        Integer integer = personIntegerMap.get(person);
        System.out.println(integer);
    }
}
What will be printed?

In my case
null 
is printed..

So what happened?

Lets put some println statements and see what happened:
package biz.tugay;
/* User: koray@tugay.biz Date: 18/12/15 Time: 21:03 */
 
import java.util.HashMap;
import java.util.Map;
 
public class TestClass {
 
    public static void main(String[] args) {
        Map<Person, Integer> personIntegerMap = new HashMap<Person, Integer>();
        Person person = new Person();
        person.setFirstName("lray");
        person.setLastName("tugay");
        personIntegerMap.put(person, 2);
        System.out.println(person.hashCode());
        person.setFirstName("kray");
        System.out.println(person.hashCode());
        Integer integer = personIntegerMap.get(person);
        System.out.println(integer);
    }
}

And what is printed in this case?
213949504
213025983
null

Well as you can see, when putting the key in the map, we used the value ending with 04, however when we wanted to get the key, the value used was the one ending with 83, thus returned object was null.

To avoid this, you can make the Person class immutable, thus an object, once constructed, can never return a different hash code during its life time!

This is a great reference about immutable objects