Newsgroup: it.comp.java
Titolo: Useful hashCode()

Hi All
How do I create a robust hashCode() method for my new classes? Can anyone
point me at a sample implementation? I can see how I can come up with a
unique return int per object, but I can't see how I'd make two equal objects
(ie. o1.equals(o2) is true) necessarily return the same int.
Thanks
Rob
Documentation on Object.hashCode():
public int hashCode()
Returns a hash code value for the object. This method is supported for the
benefit of hashtables such as those provided by java.util.Hashtable.
The general contract of hashCode is:
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.
If two objects are equal according to the equals(Object) method, then
calling the hashCode method on each of the two objects must produce the same
integer result.
It is not required that if two objects are unequal according to the
equals(java.lang.Object) <../../java/lang/Object.html> method, then calling
the hashCode method on each of the two objects must produce distinct integer
results. However, the programmer should be aware that producing distinct
integer results for unequal objects may improve the performance of
hashtables.
As much as is reasonably practical, the hashCode method defined by class
Object does return distinct integers for distinct objects. (This is
typically implemented by converting the internal address of the object into
an integer, but this implementation technique is not required by the JavaTM
programming language.)
Returns:
a hash code value for this object

(ie. o1.equals(o2) is true) necessarily return the same int.
Look at the equals method of Object.java. It simply makes the comparison:
o1 == o2
So unless the objects are the same object they will not be equal
regardless of what you do to generate a hashCode. To make the equals
method return true you must override it. Perhaps
public bolean equals( Object obj ) {
	return obj instanceof ThisClass && obj.hashCode == hashCode();
}
is all you want?
Later,
Mike
-- 
Professional Carrage Return Linefeed Conversion Services, Inc.
=================================================================
High quality CRLF programming tools, carrage-return\rlinefeed
conversion benchmarking and numerical analysis. Dot-matrix printer
carrage-return/linefeed replacement cartrages. Yes!, we do EBCDIC
CRLF conversion.\r
http://users.erols.com/mballen/crlf/

 Rob
....

Robert ~
The default Object.hashCode() returns a pointer address offset for the code
block,  so it can't be expected to be equal for objects that return true for
an equals compare.
I don't know much about the java.util.zip.CRC32 AlGoreRythm, I studied the
CRC algorithm used in PNG files, which may be identical to the java  one.  A
table of 256 32 bit (unsigned) values is generated (seeded from a specific
number) for update reference, and each byte in the byte array indexes a
table cell value, ( pretty broken up in not random ),     for each byte in
the byte array,   c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
one array reference, two exclusive or s an and  and a bitshift.
performance should be pretty good, but simplifying the bytes going in to the
crc if it could be done efficiently might be helpful.
for instance the  crc.update(toString().getBytes ) is inefficient because of
extraneous info (more bytes "x=" ).
special knolege of the conditions of the class ( what affects equals(), and
how to cheat effectively  )
Hope this helps you.
/**
@author Strongheart, est=20001203.145800
This is my first hashcode evaluator.
Converts values x,y,z in order to byte[12] array
and calculates the crc32 value for the byte array.
Should be pretty robust, that is equal Objects return equal hash codes and
most of the time as can reasonably be expected different valued objects will
produce different hash values. since the hash code is 32 bits, and x,y,z are
96 bits
some dublications are expected randomly.
*/
import java.util.zip.*;
public class hashTest
{
    public static void say(String S)
    {    System.out.println(S);    }
/**
@param AA  1 or 2 or 3
3 uses CRC32 hashcode.
*/
    public static void main(String[] AA)
    {
       obj o1 = new obj(0,1,0);
       obj o2 = new obj(1,0,0);
       obj o3 = new obj(0,0,1);
        if(AA.length>0)
        {
            String A = AA[0].trim();
            say(A);
            if(A.equals("3")){obj.how=3;say("using CRC"); }
            else if(A.equals("2")){obj.how=2; say("using MishMash"); }
            else if(A.equals("1")){obj.how=1;say("using sum");  }
        }
        say("obj.how= " + obj.how);
       say("o1 = "+o1 ) ;
       say("o2 = "+o2 ) ;
       say("o3 = "+o3 ) ;
       int x1=o1.hashCode();
       int x2=o2.hashCode();
       int x3=o3.hashCode();
       say("Ho1 = "+Integer.toHexString(x1) ) ;
       say("Ho2 = "+Integer.toHexString(x2) ) ;
       say("Ho3 = "+Integer.toHexString(x3) ) ;
       file://say(((x1>x2)?(x1-x2)+" 1 is bigger " :(x2-x1)+" 2is
bigger" ));say(((x1>x2)?(x1-x2)+" 1 is bigger " :(x2-x1)+" 2is bigger" ));
       say(((x1>x2)?(x1-x2)+" 1 is bigger " :(x2-x1)+" 2is bigger" ));
       say(((x3>x2)?(x3-x2)+" 3 is bigger " :(x2-x3)+" 2is bigger" ));
    }
}
/**
a simple test object
*/
class obj
{
    public static int hc=0;
    public int x =0,y=0,z=0;
/**
*/
    public obj()
    {
        this(0,0,0);
    }
    public obj(int x,int y,int z)
    {
        this.x=x;this.y=y;this.z=z;
    }
    public int hashCode1()
    {
        return x+y+z;
    }
    /** some dumb mish mash which might produce half robust hash  */
    public int hashCode2()
    {
        return  ( (-x+y+z)*(123^x)) +((x-y+z)*(119^y))+( (x-y+z)*(117^z)) ;
    }
/**
determins algorithim, 1 - x+y+z , 2 - mish mash , 3 - crc32 tabled hashcode
*/
    static int how = 0;
    public int hashCode()
    {
        int hc=0;
        switch(how)
        {
            case 3: hc= hashCode3();
            break; case 2: hc= hashCode2();
            break; default:hc= hashCode1();
        }
        return  hc ;
    }
    public int hashCode3()
    {
        hashTest.say("calculating hc3" );
        CRC32 crc=new CRC32();
        byte[] b = getBytes();
        crc.update(b);
/* CRC32.getValue() returns a long, we want int  */
        return (int)crc.getValue();
    }
/**
@return a byte array length = 12 representing the byte values of x,y and z
here x3,x2,x1,x0,y3,y2,y1,y0,z3,z2,z1,z0 is returned.
The array length and order will affect return.
*/
    byte[] getBytes()
    {
        byte ba[]= new byte[12];
        intToBytes(x,ba,0); /*x  */
        intToBytes(y,ba,4); /*y  */
        intToBytes(z,ba,8); /*z  */
        return ba;
    }
/*
actually fills byte positions start+0-start+3, with the byte values of the
int.
*/
    void intToBytes(int i, byte[] ba,int start )
    {
        int p=i;
        for(int n=start;n<4+start;n++)
        {
            byte q = (byte)(p&0xff);p>>>=8;
            ba[n]=q;
        }
    }
    public String  toString()
    { return "x="+x+",y="+y+",z="+z ;}
}