Reputation: 638
So, I'm trying to use a HashMap
to map my own Object
to a String
value. My object is below (with some code removed for brevity)
public class RouteHeadsignPair {
String route;
String headsign;
public RouteHeadsignPair(String n_route, String n_headsign) {
route = n_route.toLowerCase();
headsign = n_headsign.toLowerCase();
}
public String getRoute () {
return route;
}
public String getHeadsign() {
return headsign;
}
public boolean equals(RouteHeadsignPair other) {
return(other.getRoute().equals(route) && other.getHeadsign().equals(headsign));
}
public int hashCode() {
return(route.hashCode());
}
}
I'm mapping a bunch of these objects to Strings by loading data from a text file. Later on, based on (independent) user input, I try to query the HashMap
using a RouteHeadsignPair
Object. containsKey() returns false and get() returns null, as if I had never added the key into the map. But, bizarrely, if I iterate over the map using the below code (where newKey
is a RouteHeadsignPair
made from user input)
RouteHeadsignPair foundKey = null;
Iterator<RouteHeadsignPair> keysInMap = routeHeadsignToStopIdMap.keySet().iterator();
while(keysInMap.hasNext()) {
RouteHeadsignPair currKey = keysInMap.next();
if(currKey.equals(newKey)) {
System.err.println("Did find a key with an equals() == true!");
foundKey = currKey;
}
}
System.err.println("Value in map? " + routeHeadsignToStopIdMap.containsKey(newKey) + "( hashcode = " + newKey.hashCode() +
", equals = " + newKey.equals(foundKey) + ")");
System.err.println("foundKey in map? " + routeHeadsignToStopIdMap.containsKey(foundKey) + "( hashcode = " + foundKey.hashCode() +
", equals = " + foundKey.equals(newKey) + ")" );
I apologize for the code formatting, it's late and I'm getting cranky
I get the following output
Did find a key with an equals() == true!
and then
Value in map? false( hashcode = 1695, equals = true)
foundKey in map? true( hashcode = 1695, equals = true)
So, if I iterate over the keys and look for keys that return equals()
, I do find one, and the hashCode()
is the same for both of these. If the hashCode()
is the same for newKey
and foundKey
and foundKey.equals(newKey)
returns true, shouldn't HashMap.get(key)
return a value and containsKey()
return true? What am I doing wrong here?
Upvotes: 2
Views: 966
Reputation: 1503469
You're not overriding Object.equals
- you're overloading it because of the parameter type. Your diagnostic code calls your overload, but the map code doesn't (as it doesn't know about it).
You need a method with a signature of
public boolean equals(Object other)
If you use the @Override
annotation you'll get an error if you fail to override something properly.
You'll need to check whether other
is an instance of RouteHeadSignPair
first, then cast. If you make the RouteHeadSignPair
class final, you won't need to worry about whether or not it's the exact same class, etc.
Note that your hash codes will collide unnecessarily, by the way - if you use both the route
and the headSign
hashes to generate your hash code, it may help your map lookups to be more efficient. (If there are several instances with the same route but different head signs, it's useful if the map doesn't have to check for equality on all of them when looking up a key.)
Upvotes: 9