[records] updates for Preview 9. hashCode
John Rose
john.r.rose at oracle.com
Fri Jan 10 04:45:42 UTC 2020
If we don’t decide hashCode explicitly, I think we’ll back ourselves into
a bad default decision. Should the hashing logic for r.hashCode() be specified
in a portable manner? I say, “no”, since there’s no good portable solution.
Objects.hash is portable, but other than that is a poor algorithm.
Right now we don’t *specify* that we combine hashes using the base-31
polynomial, but we *do* use that stupid old thing. This is plausibly conservative
but it will get it into a worse spot than necessary. We can buy ourselves some
time by putting weasel words into Record::hashCode (or its successor) and
ObjectMethods::bootstrap. We can promise that the hashCode result
depends (typically) on all components of the record, and on nothing else.
We should also explicitly state that the method for combining the bits is
subject to change, very much like we specify that the iteration order for
Set.of and Map.of is subject to change, like this:
http://hg.openjdk.java.net/jdk/jdk/file/e9c11ba790b2/src/java.base/share/classes/java/util/Set.java#l83
Finally, for luck, we should add a pinch of salt to the hash function
to keep users on their toes, like this:
http://hg.openjdk.java.net/jdk/jdk/file/e9c11ba790b2/src/java.base/share/classes/java/util/ImmutableCollections.java#l619
(It’s an implementation detail, but for now this combiner would be enough
to buy us a better future: `(h,x) -> ((h*31)+x)^SALT`)
If we aren’t cautious about this, I’m afraid that users will eventually discover
that we are using the Objects.hash algorithm, we will be pressured to
document it, and then we’ll be locked out from an easy improvement to
records. It’s easier to introduce the salt before that happens.
I don’t think we should even promise that the record hashCode is mixed
from the hashCodes of the components. That’s TMI, and it boxes us in
without telling the user anything useful. All we need to do is promise
that a record type’s hashCode fulfills the Object contract, especially
relative to the record’s equals method. No other promises, plus a warning
that result is subject to change. And then rub some salt on it to keep
it clean, as with Set.of and Map.of.
— John
More information about the amber-spec-experts
mailing list