在使用HashMap、HashSet等数据结构时,是否需要重写hashCode方法?

3
问题在标题中。我使用如下的HashMap
Map<Player, Partner> m = new HashMap<Player, Partner>();
//do some on m

其中PlayerPartner都是代表数据模型的POJO

public class Player{

    private int id;

    private String name;
    //etc, GET, SET
}

public class Partner{

    private int id;

    private String name;
    //etc, GET, SET
}

我想说,如果两个类的对象具有相同的id,则这两个对象是等价的。因此,我应该像这样编写hashCode
public int hashCode(){
    return id;
}

这是一种正确的做法吗,当我使用HashMap或类似的东西时,为什么要使用它?


如果您正在讨论等价性,那么您应该重写“equals”方法。 - Leon
@Leon 不完全是,我不明白为什么在使用HashMap时我应该覆盖shashCode。 - St.Antario
对于DTO,您应该始终重写hashcode、equals和toString方法。 - Leon
2个回答

8

这样的hashCode会起作用。您还必须以一致的方式覆盖equals

@Override
public boolean equals(Object other)
{
    if (!(other instanceof Player))
        return false;
    Player op = (Player) other;
    return id == op.id;
}

是的,我已经了解了覆盖hashCode和equals方法。但我不明白为什么我应该这样做。例如,为什么每当我使用HashMap时都必须重写equals?如果我覆盖了equals而没有覆盖hashCode会发生什么? - St.Antario
@St.Antario hashCode和equals都用于在HashMap中定位键。两个不同的键可能具有相同的hashCode(即使它们没有,它们也可能映射到HashMap中的同一个桶中,因为桶的数量远小于可能的哈希码数量),因此使用equals来确定它们是否实际上相等。 - Eran
如果你重写了equals方法而没有重写hashCode方法,那么hashCode的默认实现将被使用。因此,两个具有相同id的Player(你认为它们是相等的)可能具有不同的hashCode,这意味着它们可能被放置在HashMap中的不同桶中,这意味着containsKey可能会错误地返回false,并且你可能能够在Map中放置相同的键两次。 - Eran
@St.Antario 正确实现 equalshashCode 是一本书的主题。使用这些方法来实现 Java Collections API 是另一本书。你应该独立地阅读相关资料。 - Boris the Spider

1

对象被存储在哈希桶中。例如,如果您有100个对象,其中50个返回哈希码值"123",其余50个返回"124",则它们将被存储在不同的两个桶中,从而减少所需的搜索时间。

在搜索时,首先需要找到对象所属的桶,一旦找到桶,则调用equals方法找到对象。

与将所有对象存储在一个地方(难以搜索)相比,基于哈希的集合将具有相同哈希码值的对象分组在一起,每个这样的组都存储在称为哈希桶的位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接