David Szalai
David Szalai

Reputation: 2539

Java hashCode changes over time (not due to fields)

According to the hashCode/equals contract if two objects are equal the must have the same hashCode - at least it is how I know it. Consider the following implementation:

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!");
    }
}

With little modifications we can get a less extreme variant:

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

I tested it (not with the getYear though), and the condition were true (the hashCodes were not equal).

Is it legal if the hashCode changes over time even if the object's fields are unmodified? I could not find any resources about this specific implementation. I know about the problem with collections, but my question is if the hashCode implementation is legal according to the contract/spec.

PS: It is a challenge question, I answered that it's not legal, but I am not sure since I at first look at the code, equals and hashCode are satisfiyng the simple contract.

Upvotes: 0

Views: 993

Answers (3)

Sleiman Jneidi
Sleiman Jneidi

Reputation: 23329

It is legal (the compiler wont complain about it) but you shouldn't be doing it. HashCode should be consistent (returns the same integer value given the same key).

From the Java Docs of hashCode

the hashCode method must consistently return the same integer

Your hashCode is exactly the opposite of that.

Upvotes: 2

npinti
npinti

Reputation: 52185

I think that if the .equals method fails, then the .hashcode should also fail.

That being said, it will most likely create more problem than it will ever solve if two object yesterday where considered to be equal but now they are not, because as far as the object is concerned, none of its fields where changed. (Think of systems which run for days, for instance).

I would recommend that you have the .hashcode() depend on the object itself rather than something which will change and is outside of the object. If this is not an option, you will need to document it heavily.

Upvotes: 0

Breandán Dalton
Breandán Dalton

Reputation: 1639

As the hashcode is used to place and then find objects that are stored in hashmaps, a class whose hashcode changes over time will make it impossible to use in a hashmap.

Upvotes: 1

Related Questions