Link to home
Start Free TrialLog in
Avatar of embert
embert

asked on

Hash code

Can anybody explain the hash code? how is it related to equals() method?
Avatar of _lychee_
_lychee_

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.

hashCode obeys:
1. hashCode of an object doesn't change
2. hashCode of 2 objects that are equal() must be the same

and hashCode is hopefully different for 2 different objects...
Extracts from java.lang.Object

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:

1. 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.

2. If two objects are equal according to the equals(Object) method, then calling the <code>hashCode</code> method on each of the two objects must produce the same integer result.

3. It is not required that if two objects are unequal according to the java.lang.Object.equals 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 Java programming language.)

-------------

As you can see last para says that, the current implementation of JVM from Sun will give return integers which are actually the address of the object in memory.

So, theoritally the rules are laid for how hashCode should function, in actuals, it is implemented as described above.

The following program demonstrates the above:
public class Test {

  public boolean equals(Object obj) {
    return true;
  }

  public static void main(String args[]) {
    Test t1 = new Test();
    Test t2 = new Test();
    System.out.println("T1's hash code: " + t1.hashCode());
    System.out.println("T2's hash code: " + t2.hashCode());
  }
}

js.
??
ur class is abit off.... since all objects of Test are equal, u should override hashCode to return the same number...
ASKER CERTIFIED SOLUTION
Avatar of sgoms
sgoms

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
A small change in sgoms comments:

The reason why str1 and str2 has same hashCode is not bcos of sr1.equals(str2). The foll program demonstrates it:

public class Test {

  public boolean equals(Object obj) {
    return true;
  }

  public static void main(String args[]) {
    Test t1 = new Test();
    Test t2 = new Test();

    System.out.println("t1's hashCode: " + t1.hashCode());
    System.out.println("t2's hashCode: " + t2.hashCode());
    System.out.println("value of equals() fn: " + t1.equals(t2));
  }
}

Althought the equals of the two objects returns true, the hashCode are not same.

js.
lychee:

not necessary. bcos the actual implementation in JVM is:

-----extract from spec-----
This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not ...
-----extract from spec-----
lychee:

not necessary. bcos the actual implementation in JVM is:

-----extract from spec-----
This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not ...
-----extract from spec-----

js.
huh?
the contract of hashCode is such that if equals remains true, the hashCode must be equal....

in ur Test class, u override equals to return true for any objects of type Test... therefore u must override hashCode to return the same integer for all objects... otherwise the default hashCode will be used which, in general, does not give the same integer for 2 objects...

think of it as
equals => hashCode equal
but not the converse...
Yes in the class Test hasCode needs to be overridden.
In case of equals function shud'nt u chk for,

if(obj!=null && obj instanceof Test)
  return true;
else
  return false;

I'd like to know how to overdide hashCode to return a unique value. does it have to be a native implementation?
___________________________________________________________

The following example uses String class which has overridden equals & hashCode.


class hashCodeTest{

    public static void main(String args[]){
              String str1=new String("Element");
                  String str2=new String("Element");
          System.out.println("Str1's hash code: " + str1.hashCode()); //str1.equals(str2) is true
          System.out.println("Str2's hash code: " + str2.hashCode());
            }
    //String calcuates the hashCode by returning a value s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]                

}

The above function returns the same hashCode for str1 & str2
js,

As equals() needs to be overridden to return true for same objects hashCode needs to be overridden to return same values if equals() is true.
check out this site for a sample implementation of that.
http://www.ibm.com/java/education/portingc/WellMannered.html#HashCode
exactly js,

the hasCodes ought to be same according to spec.
" 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. "

so if t1.equals(t2) is true then the hasCode() must return the same integer value.

It does not return the same value 'cos you have not overridden it.

String class overrides hasCode to return a int,
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]  

-sgoms
hashCode() generates a integer value according to the procedure it uses.

the hashCode() in Object class return a unique value for each object(I mean object reference).

if two objects are refernce to same then they will have same hashCode.

the hashcode() in Object follows a procedure which is based on memeory references to genreate the hashcode unique value.

the hashcode() and equals() infact uses the memeory refernces as the underlying mechanism to do the things.
//go through the following code thimngs will be clear.
insert one of hte three statemnets at the
//expected line comment            in the program
test c=new test(2);
test b=new test(1);
test b=a;


public class trial2
{
      
public static void main(String args[])
{
   test a=new test(1);

//expected one of the above lines here



   System.out.println("a`s:"+a.hashCode
   ()+"b`s:"+b.hashCode());            
   if(a.equals(b))                
     System.out.println("equals");


      
      }
}

class test
{
      int i;
      public test(int i)
      {
            this.i=i;
      }
}



 
so what did u do different that u get to 'propose' answer?

if anybody here has the right ,everybody will agree that u r not  amongst them,nor me.
Avatar of embert

ASKER

thanks for the discussion.

Lychee: you comments are very helpful, but unfortunately, I cannot accept two answers at the same time.  
u can certainly post another question for lychee.
enjoy and happy programming
:-)
chintal_stud,
Please do not post ur comments as answer when there is a discussion going on.
Moreover your comments are way off the mark. please be absolutely sure abt ur statements b4 locking the question. No offense meant.
____________________________________________________________

hasCode() & equals() should be implemented in a class.
Thanks to mbormann, Java Cookbook shows an excellentway to implement equals & hashCode.
I went thru quite a few Java source files(String, Integer, Data, Calendar...) which has hashCode() implemented in them.
None of them had a native implementation. Is there any Java class that does native implementationof hashCode() ?

I have modified the Test class, so that its got a few varaibles in it(primitive int, boolean, String object).
this is how the equals() & hashCode() shud be implemented.

public class Test {
            private int myPrimitive=1;
            private boolean myBoolean=true;
            private String myObject = new String("String");
            
            public boolean equals(Object obj) {
             if (this == obj) return true;
             if (obj == null || getClass() != obj.getClass()) return false;
             Test other = (Test)obj;
     if (myPrimitive != other.myPrimitive) return false;
     if (!myObject.equals(other.myObject)) return false;
             return true;
            }
            public int hashCode(){
                int hash=0;
                        hash = hash*37 + myPrimitive;
                        hash = hash*37 + (myBoolean ? 1:0);
                        hash = hash*37 + myObject.hashCode();
                        return hash;
            }
            
            public static void main(String args[]) {
              Test t1 = new Test();
                  Test t2 = new Test();
                  System.out.println(t1.equals(t2)); //when equals() returns true the hashCode is same
                  System.out.println("T1's hash code: " + t1.hashCode());
              System.out.println("T2's hash code: " + t2.hashCode());
                                    
                  t1.myObject="String1";
                  t2.myObject="String2";
                  System.out.println(t1.equals(t2)); //when equals() returns false the hashCode alters. though it necessarily need not be different
                  System.out.println("T1's hash code: " + t1.hashCode());
              System.out.println("T2's hash code: " + t2.hashCode());
                  
            }
}
___________________________________________________________
Output:

true
T1's hash code: -1808117329
T2's hash code: -1808117329
false
T1's hash code: -217104482
T2's hash code: -217104481

the URL suggested by mbormann is super..please check that out for a more elaborate explanation!

-sgoms
i don't have the java source handy (deleted it by mistake :( ) but i think Object would have a native implementation.
lychee,

the Object.java file contains just,
    public native int hashCode();
no implementation.

Iam yet to locate a Java class that has a native implementation for hashCode.

If you can point me to it that'd be great!
Thanks,
sgoms
iam too late to add the comments, but still:

i was trying show:

1. Overriding equal class alone will not cause a compiler error or runtime error.
  This means overriding equals alone is syntactically and semantically correct. My example was trying to analyze this point.

2. The spec or the VM implementation does not IMPOSE a "restriction" that if equals method is overridden, then hashCode method also should be overridden.

3. The spec for hashCode function says: "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"
  It means, this method is a kind of Adapter method for a particular job. Just like adapter classes are dummy wrappers, these methods can also be dummy calls and implemented as and when needed.

I agree with the guys here in the fact that it is a good programing practice to "always implement this function with the CONTRACT intact"

js.
sgoms,
if u get that pls lemme no 2.
thx