为什么我的HashSet使用相同的hashCode存储2个相同的对象?

时间:2013-11-01 23:18:02

标签: java hashcode hashset

我正在完成学校作业,我需要存储一堆联系人。每个联系人都有HashSet个社交网络帐户,地址和电话号码。

我不想在HashSet中存储同一对象的多个副本,因此我已经为每个对象覆盖了hashCode()equals()方法。

但是对于我的社交网络帐户对象,我的HashSet会存储两次相同的对象! 我有两个不同的对象:

SocialNetworkAccount s1 = new SocialNetworkAccount(SocialNetworkAccount.AccountType.FACEBOOK, "wallcrawler123");

SocialNetworkAccount s2 = new SocialNetworkAccount(SocialNetworkAccount.AccountType.FACEBOOK, "wallcrawler123");

s1.equals(s2)返回trues1.hashCode() == s2.hashCode()返回true,但s1 == s2返回false!为什么呢?

这是我正在使用的hashCode()方法:

public int hashCode() {
    int prime = 31;
    int result = 1;
    result = result*prime + type.hashCode();
    result = result*prime + id.hashCode();
    return result;
}

4 个答案:

答案 0 :(得分:2)

==运算符比较引用。由于有两个不同的对象,它们的引用会有所不同。

SocialNetworkAccount s1 = new SocialNetworkAccount(SocialNetworkAccount.AccountType.FACEBOOK, "wallcrawler123");

SocialNetworkAccount s2 = s1;

if (s1 == s2) { 
    System.out.println("The references are the same."); 
}

答案 1 :(得分:2)

我怀疑问题是您的equals方法覆盖Object's equals method,其中Object作为参数。

我怀疑您的equals方法的参数为SocialNetworkAccount,而不是Object。我无法确切知道,因为您还没有发布equals方法,但这是一个可能的解释。在这种情况下,equals中的Object方法被覆盖,因此当HashSet(最终)调用它时,它会调用Object&# 39; s equals方法,用于比较引用以查看它们是否相同。

如果是,请修改您的equals方法以接受Object而不是SocialNetworkAccount,以便正确覆盖equals

此外,当一个打算覆盖另一个方法的方法实际上没有覆盖它时,使用@Override注释将会捕获。

答案 2 :(得分:1)

hashCode方法用于粗略地为表分配条目,但equals(...)方法必须返回true才能将两个实例视为相同。

由于您没有向我们展示equals方法,我假设您没有创建自己的版本,这意味着HashTable正在使用默认实现,a == b并且您的两个实例不是同一个实例,因此返回false,因此表中有两个条目。

您需要做的是实现equals方法:

public boolean equals(Object o) {
    if (o == this) {
        return true;
    }
    if (o instanceof SocialNetworkAccount) {
        SocialNetworkAccount their = (SocialNetworkAccount)o;
        return xxx.equals(their.xxx ) &&  yyy.equals(their.yyy) && ...;
    }
    return false;
}

将xxx和yyy替换为类中的值。

请参阅hashCode and equals contract

答案 3 :(得分:1)

也许你做过这样的事情?

SocialNetworkAccount s1 = new SocialNetworkAccount(SocialNetworkAccount.AccountType.FACEBOOK, "foo");
SocialNetworkAccount s2 = new SocialNetworkAccount(SocialNetworkAccount.AccountType.FACEBOOK, "bar");

hashSet.add(s1);
hashSet.add(s2);

s2.setNickname("foo");

System.out.println(s1.equals(s2));  // true
System.out.println(hashSet);        // [FACEBOOK:foo, FACEBOOK:foo]