Lew said:
And, indeed, once again once again, 'String' has already provided such a method.
I don't see what the big to-do is about 'Object' having 'hashCode()' defined. It's
just fine as an address proxy in the default implementation, never mind its use
for hashing, and the override to provide value equality is exactly the effort needed
for classes that need a "real" hash, only at least it's in the very class whose logic
it is, rather than artificially separated into a separate 'Hasher' type.
So once again once again, the existing mechanism shows itself to be at worst
not much worse than the proposal.
Also, once again once again, the hash must match the idea of equality for the
type. I don't notice anyone arguing (yet) that 'equals()' should not be present
in 'Object'. Best practices once again once again promote keeping 'equals()',
'hashCode()', 'compareTo()' (where present) and 'toString()' consistent with
each other.
So once again once again once again once again we see the status quo
being pretty much equivalent once again once again to the proposal
once again.
Nothing in the hypothetical design prevents String, or any other class,
from defining a hashCode method, or multiple methods, with access to
private data or native code. Objections on this basis are therefore
without basis. I'm sorry if you find this confusing, but it's really
very simple.
It's also true that the majority of hash functions should depend only
on publically available data. This is not "rubbish" but a direct
consequence of how hashing works: objects that compare equal must hash
to the same value. In a small number of cases, using a private member
to cache the result of the hash calculation turns out, on average, to
be better than not cacheing it. This takes us back to the previous
point.
As you point out, the current design is not all that bad, but it's also
limiting and error prone. Limiting because a class can only have one
hash function when several might be useful: for instance, String has
equalsIgnoreCase but no hashCodeIgnoreCase. If you want to hash by
object identity for a class that overrides equals() and hashCode(), you
have to use a completely different implementation of the standard hash
map. Error prone because it takes concerns that should be kept together
(hashing is a concern of the map, not the object being hashed) and
divides them into otherwise unrelated classes. If you want to override
equals() for a class, how do you know where to look for hash maps that
might be affected?