2010-11-24 85 views
5

最近我一直在使用Java的HashMap,并且遇到了一些有趣的行为。我目前使用它来存储具有多个字段的键/值对象。要做到这一点,我已经重写hashCode()和equals()方法如下:重写hashCode()和equals()的Java HashMap不会返回任何数据

public final class TransitionState { 

private String mStackSymbol; 
private String mTransitionSymbol; 
private int mState; 

private static final int HASH_SEED = 7;  //Should be prime 
private static final int HASH_OFFSET = 31; 

//Constructor and getter methods here 

public boolean equals(TransitionState other) { 

    //Check that we aren't comparing against ourself 
    if (this == other) { 
     return true; 
    } 

    //Check that we are not comparing against null 
    if (other == null) { 
     return false; 
    } 

    //Check fields match 
    if ((mState == other.getState()) && 
     (mTransitionSymbol.equals(other.getTransitionSymbol())) && 
     (mStackSymbol.equals(other.getStackSymbol()))) { 

     return true; 

    } else { 
     return false; 

    } 
} 

public int hashCode() { 
    int intHash = HASH_SEED; 

    //Sum hash codes for individual fields for final hash code 
    intHash = (intHash * HASH_OFFSET) + mState; 
    intHash = (intHash * HASH_OFFSET) + (mTransitionSymbol == null ? 0 : mTransitionSymbol.hashCode()); 
    intHash = (intHash * HASH_OFFSET) + (mStackSymbol == null ? 0 : mStackSymbol.hashCode()); 

    return intHash; 
} 
} 

现在,我能够把项目中的地图没有问题。但是,检索它们是另一回事。每当我尝试从HashMap获取()时,都会返回NULL。我编写了一些测试代码来迭代Map和打印值,这是因为我的关键对象的hashCode()与我在我的映射中具有的匹配相匹配,并且与已知值相等的情况下返回true,所以令人困惑。输出示例如下(请参阅从表底第四转变):

Transition Table: 
State Symbol Stack Move 
-------------------------- 
1, a, b, (1, pop) with key hashcode 212603 and value hashcode 117943 
0, b, a, (0, pop) with key hashcode 211672 and value hashcode 117912 
1, b, z, (1, push) with key hashcode 212658 and value hashcode 3459456 
0, a, b, (0, pop) with key hashcode 211642 and value hashcode 117912 
1, a, z, (0, push) with key hashcode 212627 and value hashcode 3459425 
0, a, a, (0, push) with key hashcode 211641 and value hashcode 3459425 
0, a, z, (0, push) with key hashcode 211666 and value hashcode 3459425 
0, b, z, (1, push) with key hashcode 211697 and value hashcode 3459456 
1, b, a, (1, pop) with key hashcode 212633 and value hashcode 117943 
1, b, b, (1, push) with key hashcode 212634 and value hashcode 3459456 

ababba 

Transition from (0, a, z) with hashcode 211666 
transition.equals(new TransitionState(0, "a", "z")) = true 
HashMap containsKey() = false 
Transition not found 
false 

正如你所看到的,与地图的对应的键匹配散列码,但我被告知,是不存在的。我尝试调试HashMap的containsKey()方法,该方法执行get(),检查是否为NULL。进入get()会显示循环,只有在返回NULL之前运行一次。所以,这是一个HashMap问题(可能不是)或(更可能),我可能做错了什么?预先感谢您的帮助。

回答

19

您还没有覆盖equals正确......你需要

public boolean equals(Object other) 

目前你只是超载它。

基本上真正覆盖仍然可以做同样的工作作为现有一个,但有一个测试第一:

if (!(other instanceof TransitionState)) 
{ 
    return false; 
} 
TransitionState otherState = (TransitionState) other; 
// Now do the rest of the comparison 

请注意,您不需要为空检查在这种情况下,它会通过instanceof测试失败。

这些天Java允许您添加注释告诉编译器你真的想重写父类的方法:

@Overrides 
public boolean equals(Object other) 

现在,编译器会告诉你,如果你的名字拼写错误或弄错签名。

+2

总是应该使用`@ Overrides`的完美理由。 – 2010-11-24 17:48:14

+0

@matt b:我正要补充一点:) – 2010-11-24 17:48:48

2

Jon是正确的。另外,你应该做到以下几点:

让你的实例变量决赛:

private final String mStackSymbol; 
private final String mTransitionSymbol; 
private final int mState; 

如果你不能做到这一点,那么要确保你把物品进入地图后,你不改变这些变量的值。如果状态在您将它们放入地图后发生变化,您将无法再次将它们取出(至少不能通过它们的原始值)。

相关问题