Hi,

Our use case is that we have different instances of an application
running in a cloud environment and a precomputed hash code is used
downstream to see if object instances generated in different
application instances are the same or not.

An enum was later added to our model which caused the weird behavior
that instances generated by the same application instance had the same
hash, but instances generated by another application instance did not.

So it was weird to me that all of the other fields which either
consisted of Strings, primitives, collections or elements ending in
Strings and primitives generated the same hash code each time between
applications and executions and enums did not.

I understand now that relying on a specific hashcode implementation is
foolish, but because String worked this way I thought it would be nice
if enum worked this way too. But I realize now that the way String does
it, is in fact wrong (but part of unchangeable history) instead of the
other way around.

Kind regards,

Dave

On Thu, 2022-03-17 at 15:59 +0100, Raffaello Giulietti wrote:
> Hi,
> 
> specifying a fixed hashCode() algorithm has the important drawback
> that 
> it prevents evolution.
> 
> For example, as you note, String has a strictly specified algorithm
> [1] 
> that was perhaps a good one in the early days of Java (around 1995)
> but 
> has shown its deficiencies over the years. In particular, it's easy
> to 
> construct collisions, which might impact the performance of popular
> and 
> heavily used hash based data structures, like HashMap and HashSet,
> under 
> some forms of cyberattack.
> 
> Unfortunately, while better String hash algorithms have been
> proposed, 
> they cannot be adopted, as too much code out there relies on the 
> specific details of String::hashCode. (Even bytecode for switches
> over 
> String relies on that particular spec.) It's far too late now to
> change 
> the spec, even for the better.
> 
> In retrospect and IMO, fixing String::hashCode in the spec was a 
> (understandable) mistake.
> 
> 
> More generally, client code that relies on details of any popular 
> library hashCode() implementation has a dangerous dependency on such 
> details and impairs evolution of the library itself (as the example
> with 
> String shows).
> 
> To leave the door open for better implementations proposed in some 
> future, it is best to avoid specifying the details of hashCode(), as 
> done in Record::hashCode [2] ("Implementation Requirements"). After
> all, 
> the general contract reads [3]: "This integer [the hash] need not
> remain 
> consistent from one execution of an application to another execution
> of 
> the same application."
> 
> 
> But what is the use case you have for which you would like a firmly 
> specified Enum::hashCode?
> 
> 
> Greetings
> Raffaello
> 
> ----
> 
> [1] 
> https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html#hashCode()
> [2] 
> https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Record.html#hashCode()
> [3] 
> https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#hashCode()
> 
> 
> 
> On 2022-03-17 13:49, dfranken....@gmail.com wrote:
> > Dear all,
> > 
> > Currently enums do not have a well-defined hashCode()
> > implementation so
> > they defer to Object.hashCode() which just uses an internal
> > mechanism
> > to determine the hashcode, likely based on the object's place in
> > the
> > heap.
> > 
> > This may confuse a lot of developers as other classes such as
> > String do
> > have a well-defined hashcode which is consistent across multiple
> > JVM's.
> > 
> > Could it be a good idea to make enums' hashCode() method more
> > reliably
> > and predictable? For instance by using the hashcode of the name of
> > its
> > value?
> > 
> > For example:
> > 
> > class MyEnum { A, B }
> > -> A.hashCode() == A.name().hashCode()
> > 
> > Kind regards,
> > 
> > Dave Franken

Reply via email to