1

我正在尝试找到有关如何使用自定义对象作为 HashMap 的键或存储在 HashSet 中的对象的权威文档。

通过阅读各种帖子,我以某种方式发现您应该覆盖自定义对象中的两个方法 equals() 和 hashCode() (例如覆盖 Java 中的 equals 和 hashCode)。

但是,当我阅读HashSetHashMap的 Oracle/Sun 官方 Javadocs 时,他们根本没有提到重写这些方法。这些说明是否隐藏在文档的其他地方?如果是这样,我在哪里可以找到它们?

4

5 回答 5

3

不需要重写equalsand hashCode,但你需要有一致 equals的andhashCode方法。

也就是说,如果obj.equals(obj2),那么它一定是obj.hashCode() == obj2.hashCode()。相反(equals()具有不相等值的非对象hashCode())应该尽可能频繁地为真以获得良好的性能,但这不是要求,如果您的对象具有超过 2^32 个状态,则不能总是满足)。

默认值equals()hashCode()方法遵循这一点并具有标识语义 - 对象只有在它们实际上是相同的对象(obj == obj2)时才相等。

如果您想要值语义 - 例如,具有相同状态的两个对象相等,您应该覆盖这些方法。

于 2013-02-20T00:10:41.113 回答
0

Collections API 用 equals() 和 hashCode() 来描述合约。如果您希望一个键的多个实例彼此相等,那么您需要按照 Object 类指定的协定重写 equals() 和 hashCode()。

Set 接口描述了它的合约:

更正式地说,集合不包含一对元素 e1 和 e2 使得 e1.equals(e2),并且最多包含一个空元素。正如它的名字所暗示的,这个接口模拟了数学集合抽象。

equals() 和 hashCode() 的合约由 Object 类指定。

在“Effective Java”中,Joshua Bloch 建议您在覆盖hashCode时始终覆盖equals,以避免违反这些约定。

于 2013-02-20T00:06:41.213 回答
0

在java.lang.Object的合同中对其进行了详细讨论。

于 2013-02-20T00:06:52.877 回答
0

在 和 的文档中SetMap它们是它们实现的接口。

该要求不是任意的,它是保证接口的方法按预期工作的唯一方法 - 通过能够判断何时可能是不同的 Java 对象的键应该真正被视为相同的键 - 例如,"abc""ab" + "c"是不同的对象,但 的实现equals确保它们被认为是相同的键。至于hashCode,需要在作为这些接口基础的数据结构中找到有意义的位置。

于 2013-02-20T00:08:30.007 回答
0

据我所知,密钥必须是不可变对象。

如果它是可变的,它的哈希码在添加到映射后可以改变。然后地图可能无法找到它

在java Hashmap中将自己的类设置为键

这是一个说明这一点的例子:

import java.util.HashMap;
class Test{

    public int i=0;
    @Override
    public int hashCode() {
        return i;
    }
}

public class Main {
    public static void main(String[] args) {

        HashMap<Test, String> hm = new HashMap<>();
        Test t1 = new Test();
        hm.put(t1, "found");

        System.out.println(hm.get(t1));

        t1.i=2;

        System.out.println(hm.get(t1));


    }


}

/*
output:
found
null
*/
于 2013-02-20T00:08:50.853 回答