2015-07-19 82 views
0

我有这样的结构:为什么我从字符串中获取错误的HashCode?

private HashMap<Integer,HashMap<Object,Integer>> commandList= new HashMap<>(); 

填充这样:

{1={1=2, 2=3, 3=4, -999=-999, -998=-998}} 

从这个代码:

if ((msgTypeTemp=commandList.get(this.msgType).get(msgContent))==null) { 
    Object s= "1"; 
    System.out.println("Class of s: "+s.getClass().getSimpleName()+"\nClass of msgContent: "+msgContent.getClass().getSimpleName()); 
    System.out.println("msgMap:\n"+msgMap); 
    System.out.println("commandList:\n"+commandList); 
    System.out.println(s.hashCode()); 
    System.out.println(msgContent.hashCode()); 
    System.out.println(commandList.get(this.msgType).get(s)); 
    this.msgType=JSockOS_UndefinedMsg.MSG_CODE; 
    specialMsg=true; 
} else {     
    this.msgType=msgTypeTemp; 
    if (specialMsgType(this.msgType)){   
     specialMsg=true; 
    } 
} 

HashMap是通用型<String,Integer>

但是,每当我CA得到msgContent上的get方法,结果发现代替"1"的散列代码,它是一个散列代码,它直到被设置为0,然后在get方法调用之后改变了

这仅发生于使用"msgContent"参数调用...

如果我用这个:System.out.println(commandList.get(this.msgType).get(s));

它返回 “2” 果然......

看也是这个形象,它可能有帮助。

Notice the differences in the two yellow boxes showed while debugging

msgContent得到这样上面的代码之前改变:

这是第一:2.1。 然后它得到:1.

仍然是一个字符串。

msgContent=msgContent.toString().split(Pattern.quote("."))[1]; 
do(msgContent); // a methods which implements the code showed before. 

//msgContent is a parameter, --> public void do(Object msgContent) 

[编辑]: 发现问题:msgContent是495个字符...会解决它的变化和更新!

+0

你确定内部'HashMap 的键是否总是相同的类型?如果没有,尝试这样做以避免这些问题。记住'new Integer(1)'不会返回与“1”相同的哈希码。 –

+0

我的散列表不会有相同类型的键,但每个键元素都会提供散列码和相同的方法来获得正确的散列码相关决定。 在这个例子中,我的hashmap仅包含键值中的字符串。事实上,我测试了这个试图通过键(字符串)“1”获取值。 msgContent也是一个字符串(在运行时),它包含“1”,但它似乎是一个不同的对象... –

+1

在你发布的图像中,msgContent的细节是不完整的,好像它的值是“1”或稍微不同的东西,这会产生巨大的差异。 –

回答

1

即使String是不可改变的hashCodecomputed lazily性能方面的原因,as shown here

public int hashCode() { 
    int h = hash; 
    if (h == 0 && value.length > 0) { 
     char val[] = value; 

     for (int i = 0; i < value.length; i++) { 
      h = 31 * h + val[i]; 
     } 
     hash = h; 
    } 
    return h; 
} 

至于你的实际的问题是,你完全可以肯定,你的钥匙是String?您在那里提供的类型是<Object, Integer>,而不是<String, Integer>。如下图所示

我的测试情况下工作正常(这个打印elseSide):

public static void main(String... args) { 
    HashMap<Integer, HashMap<Object, Integer>> map = new HashMap<>(); 
    HashMap<Object, Integer> innerMap = new HashMap<>(); 
    innerMap.put("1", 2); 
    innerMap.put("2", 3); 
    innerMap.put("-999",-999); 
    innerMap.put("-998",-998); 
    map.put(1, innerMap); 

    int msgType = 1; 
    String msgContent = "2.1"; 
    msgContent = msgContent.toString().split(Pattern.quote("."))[1]; 

    System.out.println(map); 

    if(map.get(msgType).get(msgContent) == null) { 
     System.out.println("ifSide"); 
    } else { 
     System.out.println("elseSide"); 
    } 
} 

我想你应该尝试添加以下调试语句:

HashMap<Object, Integer> innerMap = commandList.get(this.msgType); 
for(Map.Entry<Object, Integer> entry : innerMap.entrySet()) { 
    System.out.println("KeyClass: " + entry.getKey().getClass() + 
      "\tKeyValue:" + entry.getKey()); 
    // This will make sure the string doesn't have any unprintable characters 
    if(entry.getKey() instanceof String) { 
     String key = (String) entry.getKey(); 
     System.out.println("Key Length: " + key.getLength()); 
    } 
} 

我不认为你的钥匙在你的内部映射中实际上是一个String,或者String以某种方式具有不可打印的字符。对于一个字符String来说,630719471的散列值太高。 msgContent也可能有不可打印的字符。

+0

,我确定我的hashmap只包含条目。 但我想自由地添加不同的键类型,这将肯定会实现哈希码和等同的方法。 –

+0

完成,一切都是STRING。 “KeyClass:类java.lang.String \t KEYVALUE:1个 KeyClass:类java.lang.String \t KEYVALUE:2个 KeyClass:类java.lang.String \t KEYVALUE:3个 KeyClass:类java.lang中.String \t键值:-999 KeyClass:类java.lang.String \t键值:-998 –

+0

@FrancescoRizzi查看更新后的编辑,我只是​​想的东西 – durron597

相关问题