Java HashMap和关键对象的问题我翻了一遍自己 [英] Issues with Java HashMap and key Object I rolled myself

查看:91
本文介绍了Java HashMap和关键对象的问题我翻了一遍自己的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我试图用 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 ,然后施放。如果你制作 RouteHeadSignPair class final,你就不用担心它是否是完全相同的类。



请注意,如果您同时使用 route ,那么您的哈希码将不必要地碰撞, c> headSign 哈希来生成你的哈希码,它可以帮助你的地图查找更高效。 (如果有几个实例具有相同的路线但头标不同,如果地图在查找某个键时不需要检查它们之间是否相等,那么这很有用。)


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?

解决方案

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.)

这篇关于Java HashMap和关键对象的问题我翻了一遍自己的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆