Reputation: 9232
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
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
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