tags:

views:

385

answers:

6

For Every Equal Object their Hashcode must be equal. Java returns a unique hashcode if we do not override the hashCode() method

/* A program to check hashcode values for object
@Author Myth17
*/

class HashValue 
{

int x;

 public boolean equals(Object oo)
 {
 //if(oo instanceof Hashvalue) uncommenting ths gives error.dunno why? :|
 HashValue hh = (HashValue)oo;

 if(this.x==hh.x)
 return true;
 else
 return false;
 }

HashValue()
{
x=11;
}

}

class  Hashing
{
public static void main(String args[])
{
HashValue hv=new HashValue();
HashValue hv2=new HashValue();

System.out.println(hv.hashCode());
System.out.println(hv2.hashCode());

if(hv.equals(hv2))
System.out.println("EQUAL");
else
System.out.println("NOT EQUAL");
}
}

Why does uncommenting the line gives compilation error?? If the objects have unequal hashcodes, why are they shown equal even though the default hashcode varies??

+1  A: 

For starters, you need to capitalize the v in "Hashvalue"

if(oo instanceof Hashvalue)

should be

if (oo instanceof HashValue)
Peter Recore
if (oo instanceof HashValue)gives error too!!
Myth17
+6  A: 

First, in that line, you need to change Hashvalue to HashValue, since your class is actually called HashValue.

Then, uncommenting the line gives you this:

public boolean equals(Object oo) {
    if(oo instanceof HashValue)
        HashValue hh = (HashValue)oo;

    if (this.x==hh.x) {
        return true;
    } else {
        return false;
    }
}

There are a few things wrong with this:

  1. This doesn't compile because hh isn't in scope when you end up using it.

  2. The first if statement should either make sure that the function doesn't run at all when you compare two things that aren't HashValues (i.e. throw an exception), or it should return false because HashValues are never equal to other types of objects. I generally prefer returning false to throwing an exception.

  3. The second if statement is redundant, because you're just returning what the condition evaluates to.

Rework your method like this:

public boolean equals(Object oo) {
    if(!(oo instanceof Hashvalue)) {
        return false;
    }

    HashValue hh = (HashValue)oo;
    return (this.x == hh.x);
}

This isn't quite right, either. To make sure that all equal objects have the same hash code, you have to override hashCode() in HashValue, and you must make sure that it lives up to the guarantee. Here, you could just add this:

// inside HashValue
int hashCode() {
    return x;
}

The implementation is trivial because your object is just a wrapper around an int. You'll need to think harder about this as your objects get more sophisticated.

tgamblin
Understood the scope probloem.Even after making the changes you did, the ans if still equal for different hashcode. How does this work??
Myth17
You need to actually override the method. See my edits above.
tgamblin
So we have to make sure ourseleves that the equal objects have equal hashcodes? Coz java will report them as equal bcoz of the attribute matching even though the hashcode was different?
Myth17
Yes, it's up to you to implement both of these methods and make sure they behave correctly. If you don't override one or the other, equals() or hashCode() method from some superclass (e.g. Object) will get called, and it most likely won't do what you intend.
tgamblin
You should definitely NOT throw an exception if `oo` is not of the correct class. Nothing about `equals()` prohibits people from calling it with a different type, as long as it is symmetric. Just return false.
Mark Peters
Also throwing an exception in this particular implementation would break equals' spec, which says that `equals(null)` must return false.
Mark Peters
+3  A: 

HashValue and Hashvalue are two different identifiers

if(oo instanceof HashValue) works because your class-name is HashValue not Hashvalue

EDIT :

Your code doesn't work because hh isn't in scope when you are using it.

This works:

/* A program to check hashcode values for object
@Author Myth17
 */

class HashValue 
{

   int x;

   public boolean equals(Object oo)
  {
    HashValue hh=new HashValue();
    if(oo instanceof HashValue) 
       hh = (HashValue)oo;

    if(this.x==hh.x)
      return true;
    else
      return false;
  }

   HashValue()
  {
     x=11;
   }

  }

 class  Hashing
 {
     public static void main(String args[])
    {
       HashValue hv=new HashValue();
       HashValue hv2=new HashValue();

      System.out.println(hv.hashCode());
      System.out.println(hv2.hashCode());

      if(hv.equals(hv2))
        System.out.println("EQUAL");
      else
         System.out.println("NOT EQUAL");
    }
  }
Prasoon Saurav
ohh..I gt it...where I was wrong..
Myth17
why a down vote?
Prasoon Saurav
Unnecessarily constructing a new HashValue() every time you call equals is going to give you some really horrible performance if you compare a bunch of these. This is a quick fix when his method really needs to be reworked.
tgamblin
@tgamblin: Ok thanks, but a down vote wasn't necessary xD.
Prasoon Saurav
@Prasoon: it's also wrong, or at least weird, because your equals() method will say that all HashValues are equal to non-HashValues. e.g. try: new HashValue().equals(new String()). This returns true. I don't think that makes any sense.
tgamblin
+2  A: 

Equality is only determined by method equals(). And method hashCode() is used in other situations, like by Map or Set. It is somewhat like a pre-condition or hint before actually calling equals (for efficiency). So it is assumed that if 2 objects are equal (that is, equals() returns true), then their hashCodes() must return the same value.

So in your code, 2 objects are equal, as long as your overriden equals() returns true, no matter what hashCode() does. hashCode() is not called at all when comparing for equality.

This question has more in-depth information regarding to the relationship between equals() and hashCode().

bryantsai
So we have to make sure ourseleves that the equal objects have equal hashcodes? Coz java will report them as equal bcoz of the attribute matching even though the hashcode was different?
Myth17
+1  A: 
sateesh
A: 

int x; public static void main(String args[]){

       E a= new E();

      System.out.println(a.hashcode());

       E b= new E();

       System.out.println(b.hashcode());

} public int hashcode(){

       retune  x*17;

}

}

mario
Hi Mario, welcome to StackOverflow. I'm not sure what you're attempting to add here, as this question was already answered. But what you added has no description and numerous errors. -1. I suggest you click the "delete" link at the bottom of your answer unless there is significant editing to come.
Mark Peters