Java HashMap和关键对象的问题我翻了一遍自己 [英] Issues with Java HashMap and key Object I rolled myself
问题描述
HashMap
将我自己的 Object
映射到字符串
值。我的对象在下面(为简洁起见删除了一些代码)public class RouteHeadsignPair {
哈希来生成你的哈希码,它可以帮助你的地图查找更高效。 (如果有几个实例具有相同的路线但头标不同,如果地图在查找某个键时不需要检查它们之间是否相等,那么这很有用。)
String route;
字符串头像;
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;
$ b $ public boolean equals(RouteHeadsignPair other){
return(other.getRoute()。equals(route)&& other.getHeadsign()。equals(headsign ));
public int hashCode(){
return(route.hashCode());
$ / code $ / pre
我将这些对象映射到字符串通过从文本文件加载数据。稍后,基于(独立)用户输入,我尝试使用RouteHeadsignPair
对象查询HashMap
。 containsKey()返回false,get()返回null,就好像我从未将键添加到地图中一样。但是,奇怪的是,如果我使用下面的代码(其中newKey
是用户输入的RouteHeadsignPair
)遍历映射)RouteHeadsignPair foundKey = null;
Iterator< RouteHeadsignPair> keysInMap = routeHeadsignToStopIdMap.keySet()。iterator();
while(keysInMap.hasNext()){
RouteHeadsignPair currKey = keysInMap.next();
if(currKey.equals(newKey)){
System.err.println(找到一个等于(== == 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)+));
我对代码格式表示歉意,它迟到了, >
我得到以下输出
一个equals()== true!
然后
地图中的值? false(hashcode = 1695,equals = true)
map中的foundKey? true(hashcode = 1695,equals = true)
所以,如果我遍历键并寻找返回
equals()
的键,我找到了一个,hashCode()
对于这两个键是相同的。如果hashCode()
与newKey
和foundKey
和foundKey.equals(newKey)
返回true,不应该HashMap.get(key)
返回一个值并且containsKey()
return true?我在这里做错了什么?解决方案您不重写
Object.equals
- 由于参数类型的原因,您正在重载。您的诊断代码会调用您的重载,但地图代码不会(因为它不知道)。
您需要方法签名为
public boolean equals(Object other)
如果您使用
@Override
注释,如果您无法正确覆盖某些内容,则会出现错误。
您需要检查
其他
是否是RouteHeadSignPair $的一个实例先c $ c>,然后施放。如果你制作
RouteHeadSignPair
class final,你就不用担心它是否是完全相同的类。
请注意,如果您同时使用
route
和,那么您的哈希码将不必要地碰撞, c> headSignSo, I'm trying to use a
HashMap
to map my ownObject
to aString
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 aRouteHeadsignPair
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 (wherenewKey
is aRouteHeadsignPair
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 thehashCode()
is the same for both of these. If thehashCode()
is the same fornewKey
andfoundKey
andfoundKey.equals(newKey)
returns true, shouldn'tHashMap.get(key)
return a value andcontainsKey()
return true? What am I doing wrong here?解决方案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 ofRouteHeadSignPair
first, then cast. If you make theRouteHeadSignPair
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 theheadSign
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.)这篇关于Java HashMap和关键对象的问题我翻了一遍自己的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!