Java hashCode 随时间变化(不是由于字段)

Java hashCode changes over time (not due to fields)

根据 hashCode/equals 合同,如果两个对象相等,则必须具有相同的 hashCode - 至少我是这样知道的。考虑以下实现:

package Happy;

import java.time.LocalDate;

class MyClass
{
    private int id;

    public int getId()
    {
        return id;
    }

    public MyClass(int id)
    {
        this.id = id;
    }

    public int hashCode()
    {
        return LocalDate.now().getYear() + getId();
    }

    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        MyClass other = (MyClass) obj;
        if (hashCode() != other.hashCode())
            return false;
        return true;
    }
}

public class HappyNewYear
{
    public static void main(String[] args) {
        MyClass my = new MyClass(0);
        if (my.hashCode() != my.hashCode()) System.out.println("Happy New Year!");
    }
}

稍作修改,我们可以得到一个不那么极端的变体:

public int hashCode()
{
    return return (int) (System.nanoTime() + getId());
}

我测试了它(虽然没有使用 getYear),条件为真(hashCodes 不相等)。

如果 hashCode 随着时间的推移发生变化,即使对象的字段未修改,这是否合法? 我找不到有关此特定实现的任何资源。 我知道集合的问题,但我的问题是根据 contract/spec.[=21,hashCode 实现是否合法 =]

PS: 是一道挑战题,我回答说不合法,但我不确定,因为我第一次看代码,equalshashCode是满足简单契约。

由于hashcode是用来放置然后查找存储在hashmaps中的对象,因此hashcode随时间变化的class将无法在hashmap中使用。

我认为如果.equals方法失败了,那么.hashcode应该也会失败。

也就是说,如果两个对象昨天被认为是相等的,但现在它们不相等,那么它很可能会产生比它解决的问题更多的问题,因为就对象而言,none它的领域发生了变化。 (例如,想想 运行 几天的系统)。

我建议您让 .hashcode() 依赖于对象本身,而不是会改变 并且在对象之外的东西 。如果这不是一个选项,您将需要大量记录

这是合法的(编译器不会抱怨)但你不应该这样做。 HashCode 应该是一致的(returns 给定相同键的相同整数值)。

来自Java Docs of hashCode

the hashCode method must consistently return the same integer

你的hashCode恰恰相反