5

It seems that many classes (e.g. HashSet) assume that the hashCode of an object will not change. The documentation is clear about what the relationship between equals and hashCode should be.

But is it poor design to implement a hashCode that changes across an object's life-time?

sdgfsdh
  • 33,689
  • 26
  • 132
  • 245
  • 1
    The **real question** underlying your question as I see it is simply this: when should your objects be immutable, and the answer as I understand it is: whenever feasible. Mutable objects will always be necessary, but my understanding is that one should try to limit them when possible since mutability increases complexity. – Hovercraft Full Of Eels Sep 25 '15 at 15:20

5 Answers5

6

There at least needs to be point in the application where the hashCode is frozen while it is in a collection that cares. Typically, the hashCode will change while you build up the object (e.g., adding to an ArrayList), then you add it to a collection and stop changing. Later, if you remove it from the collection, you could mutate it again. I would say it is generally a best practice to use immutable data structures (ala String or your own type with finals all the way down) with collections that rely on the hashCode (e.g., HashMap key or HashSet).

Brett Kail
  • 33,593
  • 2
  • 85
  • 90
  • 1
    And btw, a similar thing occurs with comparable objects going into things like HashSet, HashMap, PriorityQueue, etc -- if the value of the object is going to change, then you should remove it, change its state, and put it back in. Otherwise, it's going to be in the wrong place in the structure, and things will break. – yshavit Sep 25 '15 at 15:20
  • erm sorry, meant TreeSet, TreeMap, etc :) – yshavit Sep 26 '15 at 17:39
3

No, it's ok that the hashCode changes when a mutable object changes its internal state.

However, once the object is in a place that expects a constant hashCode, the application must make sure that the object is not mutated such that the hashCode changes.

ZhongYu
  • 19,446
  • 5
  • 33
  • 61
  • That is not the question here. For instance, a same `String`, which is immutable, may have a different hash code from one JVM run to the other. – fge Sep 25 '15 at 15:15
  • is that the same 'life-time'? unless we are pondering some reincarnation philosophy. – ZhongYu Sep 25 '15 at 15:18
1

It depends on what you call the "lifetime". Your exact link states that:

Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer

This means that there is no guarantee whatsoever that the hash code of an object remain consistent across two different runs of the application.

But it is guaranteed that on a given run of an application, that is an instance of a JVM running Java code, the hash code of an object will never change.

The contract does guarantee this, but nothing more.

fge
  • 119,121
  • 33
  • 254
  • 329
  • I didn't downvote, but the quote continues "...provided no information used in equals comparisons on the object is modified". So it seems it's not guaranteed/required that hashCode can't change even during a single run. – Cinnam Sep 25 '15 at 15:20
  • @Cinnam but that's a given! It is not the question of the OP here... Or if it is, I have completely misunderstood the question – fge Sep 25 '15 at 15:28
  • I understood OP's question as "Can an object return different values from its `hashCode()` method provided the `hashCode()`/`equals()` relationship is honored?". My comment was just about the part of your answer where you say that it's guaranteed that hash code can never change during a single execution. I thought you meant that you are not allowed to change it even if you change `equals()` accordingly. – Cinnam Sep 25 '15 at 15:49
0

You are talking about different things. If you want use Hash(Map|Set) - keys should be an immutable objects. So in this case hashCode will be immutable too. But in common cases hashCode should be changed with object state (according to fields that make sense for hashCode).

Pavel Uvarov
  • 1,090
  • 1
  • 10
  • 16
0

hashCode does not guarantee the same result in different executions.. As the javadocs point out -

Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.

This is uncommon and some classes in the class library even specify the exact formula they use to calculate hash codes - e.g. String. For these classes, the hash code will always be the same. But while most of the hashCode implementations provide stable values, you must not rely on it.

Furthermore, some think that the hashcode is a unique handle to an object. This is wrong and an anti-pattern. For example, the Strings "Aa" and "BB" produce the same hashCode: 2112.

Shawn Mehan
  • 4,513
  • 9
  • 31
  • 51