Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating Java HashMap key

I was just wondering, what would happen if key of a HashMap is mutable, test program below demonstrate that and I am unable to understand when both equals and hashCode methods returns true and same value, why does hashmap.containsKey return false.

public class MutableKeyHashMap {

    public static void main(String []a){

            HashMap<Mutable, String> map = new HashMap<Mutable, String>();
            Mutable m1 = new Mutable(5);
            map.put(m1, "m1");
            Mutable m2 = new Mutable(5);
            System.out.println(map.containsKey(m2));    

            m2.setA(6);
            m1.setA(6);
            Mutable m3 = map.keySet().iterator().next();

            System.out.println(map.containsKey(m2)+"    "+m3.hashCode()+"       "+m2.hashCode()+"       "+m3.equals(m2));   

    }
}
class Mutable {

    int a;

    public Mutable(int a) {

        this.a = a;
    }

    @Override
    public boolean equals(Object obj) {

        Mutable m = (Mutable) obj;
        return m.a == this.a ? true : false; 
    }

    @Override
    public int hashCode(){
        return a;
    }

    public void setA(int a) {

        this.a = a;
    }

    public int getA() {
        return a;
    }
} 

This the output :

true false 6 6 true

like image 339
Abidi Avatar asked Jul 20 '11 19:07

Abidi


1 Answers

The javadoc explains it

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.

Basically, don't use mutable objects as keys in a Map, you're going to get burnt

To extrapolate, because the docs may not appear clear, I believe the pertinent point here is `changed in a manner that affects equals', and you seem to be assuming that equals(Object) is called each time contains is invoked. The docs don't say that, the wording implies they may be allowed to cache computations.

Looking at the source, it seems that because your hashCode returns a different value (was 5, now 6), it's possible that it's being looked up in a different bucket based on implementation details.

like image 50
ptomli Avatar answered Oct 07 '22 02:10

ptomli