【问题标题】:Issues with Java HashMap and key Object I rolled myselfJava HashMap 和我自己滚动的关键对象的问题
【发布时间】:2012-08-24 07:31:13
【问题描述】:

所以,我正在尝试使用 HashMap 将我自己的 Object 映射到 String 值。我的对象在下面(为简洁起见,删除了一些代码)

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());
    }
}

我通过从文本文件加载数据将这些对象映射到字符串。稍后,基于(独立)用户输入,我尝试使用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("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) + ")" );

我为代码格式道歉,太晚了,我开始胡思乱想了

我得到以下输出

Did find a key with an equals() == true!

然后

Value in map? false( hashcode = 1695, equals = true)
foundKey in map? true( hashcode = 1695, equals = true)

因此,如果我遍历键并查找返回 equals() 的键,我确实找到了一个,并且 hashCode() 对于这两个键都是相同的。如果hashCode()newKeyfoundKey 相同,并且foundKey.equals(newKey) 返回true,那么HashMap.get(key) 不应该返回一个值而containsKey() 返回true 吗?我在这里做错了什么?

【问题讨论】:

    标签: java hashmap


    【解决方案1】:

    您没有覆盖Object.equals - 由于参数类型,您正在重载它。您的诊断代码调用了您的重载,但地图代码没有(因为它不知道)。

    你需要一个带有签名的方法

    public boolean equals(Object other)
    

    如果您使用 @Override 注释,如果您未能正确覆盖某些内容,则会收到错误消息。

    您需要先检查other 是否是RouteHeadSignPair 的实例,然后再进行转换。如果您将RouteHeadSignPair 类定为final,则无需担心它是否是完全相同的类等。

    请注意,顺便说一下,您的哈希码会发生不必要的冲突 - 如果您同时使用 route headSign 哈希来生成哈希码,它可能有助于您的地图查找更有效率。 (如果有多个实例具有相同的路线但头部标志不同,则在查找键时,如果地图不必检查所有实例是否相等,这很有用。)

    【讨论】:

    • 我还建议他添加 null 检查或反向 equals() 调用
    • @EugenMartynov:我不确定您所说的“反向等于调用”是什么意思,但是是的,还有更多工作要做。将编辑。
    • 是的,我使用 (route.hashCode() ^ headsign.hashCode()) 作为我的 hashCode() 结果,但在调试时对其进行了简化。无论如何,我每条路线最多有两个头标,所以这没什么大不了的。
    • @JonSkeet instanceof 将处理空大小写。很好的答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多