arjacsoh
arjacsoh

Reputation: 9232

Retrieving an object in a Map

I am trying to retrieve an object as a key in a Map when I have changed an instance variable of it. As far as I am concerned, when I search a key object in a Map structure, it should come up when hashCode method returns the same value as initially. However, based on the following code, I cannot retrieve the object through method get() having altered the value of the variable weight:

public class Car  implements Comparable<Car> {

 int weight;
 String name;

 public Car(int w, String n) {
    weight=w;
    name=n;
 }

public boolean equals(Object o){
    if(o instanceof Car){
        Car d = (Car)o;
        return ((d.name.equals(name)) && (d.weight==weight));
    }
    return false;

}

public int hashCode(){
    return weight/2 + 17;
}

public String toString(){
    return "I am " +name+ " with weight: "+weight;
}


public int compareTo(Car d){
    if(this.weight>d.weight)
        return 1;
    else if(this.weight<d.weight)
        return -1;
    else
        return this.name.compareTo(d.name);
}

}


public static void main(String[] args) {
    Car d1 = new Car(107, "a");
    Car d2 = new Car(110, "b");
    Car d3 = new Car(110, "c");
    Car d4 = new Car(107, "a");

    Map<Car, Integer> m = new HashMap<Car, Integer>();
    m.put(d1, 1);
    m.put(d2, 2);
    m.put(d3, 3);
    m.put(d4, 16);

    System.out.println(m.get(d1).toString());
    d1.weight = 34;
    System.out.println(m.get(new Car(34, "a")));

    for(Map.Entry<Car, Integer> me : m.entrySet())
        System.out.println(me.getKey().toString() + " value: " +me.getValue());

}

The output is:

16

null

I am a with weight: 34 16

I am c with weight: 110 3

I am b with weight: 110 2

However, if I do not change the value of weight (omit the line: d1.weight = 34; ), merely using the line of code:

System.out.println(m.get(new Car(107, "a")));

the output is:

16

16

I am a with weight: 107 value: 16

I am c with weight: 110 value: 3

I am b with weight: 110 value: 2

It finds actually the object. Does it come to the expected output in both ways, or should it also in the first version have found and retrieved the object?

Upvotes: 1

Views: 125

Answers (2)

JamesB
JamesB

Reputation: 7894

System.out.println(m.get(new Car(34, "a")));

Your map returns null here because it does not contain a key object with hashcode 34.

However with

System.out.println(m.get(new Car(107, "a")));

your map does return an object because it does contain a key object with hashcode 70.

Upvotes: 0

Steven Schlansker
Steven Schlansker

Reputation: 38526

You should be very careful when storing mutable objects as keys in a hashtable. The hash code is computed only once, on object insert. If you later change the object in a way that affects its hash code, it is very likely that it will be impossible to find.

You need to remove the object and reinsert it whenever such a change is made.

Upvotes: 6

Related Questions