To: bob smith
From: Jan Burse <
[email protected]>
bob said:
Is it always technically correct to override the hashCode function like so:
@Override
public int hashCode() {
return 1;
}
Would it be potentially better if that was Object's implementation?
Maybe it would make sense to spell out what the contract for hashCode() is.
Well the contract is simply, the following invariant should hold:
/* invariant that should hold */
if a.equals(b) then a.hashCode()==b.hashCode()
It should be noted that this does not imply:
/* not implied and thus not required by the invariant */
if a.hashCode()==b.hashCode() then a.equals(b)
It is also quite unlikely that a hashCode() would satisfy the later, although
the closer it comes to the later, the better it works for HashMap, etc..
The default objects implementation of hashCode() matches the default objects
impementation of equals(). The default objcts implementation of equals() is ==.
And the default objects implementation of hashCode() is
System.identityHashCode().
The System identity hash code is stored in the object and generated by the
system. It does not change during GC although the internal object address might
change during GC. It is only 32bit although internal object addresses might by
64bit with a corresponding JVM.
Returning a constant, any constant c not only 1, would be technically correct
correct for the default implementation of the class object. Since it trivially
satisfies the invariant:
if a.equals(b) then c==c
is trivially true, since c==c is true. But it is not better. Since you would
get very degenerated HashMaps, etc..
You need to override the hashhCode() when there is danger that the invariant is
not anymore satisified. This is not the case when equals() is not overridden.
So overriding hashCode() just for fun when equals() is not overriden, usually
doesn't make sense. It will probably only slow down the hashCode() calculation.
So the following:
hashCode() = sum attr_i * c^i
Is not necessary. But it would be a possible way to go when equals() were
overriden in the following way:
equals(other) = and_i attr_i.equals(other.attr_i)
The above happens when you turn your object into a container of other objects
irrespective of the own object identity. But beware if the container contains
itself somewhere. This is why we find in the code for Hashtable the following
complication:
public synchronized int hashCode() {
/*
* This code detects the recursion caused by computing the hash code
* of a self-referential hash table and prevents the stack overflow
* that would otherwise result. This allows certain 1.1-era
* applets with self-referential hash tables to work. This code
* abuses the loadFactor field to do double-duty as a hashCode
* in progress flag, so as not to worsen the space performance.
* A negative load factor indicates that hash code computation is
* in progress.
*/
Interestingly it will return a constant for the object when it detects a loop.
Maybe one could do better... Dunno
Bye
--- BBBS/Li6 v4.10 Dada-1
* Origin: Prism bbs (1:261/38)
--- Synchronet 3.16a-Win32 NewsLink 1.98
Time Warp of the Future BBS - telnet://time.synchro.net:24