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

时间:2015-11-04 10:44:40

标签: java equals hashcode

根据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随着时间的推移而改变,即使对象的字段未修改,这是否合法?我找不到有关此特定实现的任何资源。 我知道集合的问题,但我的问题是,根据合同/规范,hashCode实现是否合法

PS:这是一个挑战性的问题,我回答说这不合法,但我不确定,因为我一开始看代码,equalshashCode都满足于简单的合同。< / p>

3 个答案:

答案 0 :(得分:2)

这是合法的(编译器不会抱怨它),但你不应该这样做。 HashCode应该是一致的(给定相同的密钥返回相同的整数值)。

来自Java Docs of hashCode

  

hashCode方法必须始终返回相同的整数

你的hashCode恰恰相反。

答案 1 :(得分:1)

由于哈希码用于放置然后查找存储在哈希映射中的对象,因此哈希码随时间变化的类将无法在哈希映射中使用。

答案 2 :(得分:0)

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

话虽这么说,如果两个对象昨天被认为是相等但现在却不是,那么它很可能会产生比它将要解决的问题更多的问题,因为就对象而言,它的所有字段都没有改变。 (想想运行数天的系统)。

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