简体   繁体   中英

Hashcode and equals

equals and hashCode method must be consistent, which means that when two objects are equal according to equals method their hashCode method should return the same hash value.

Java returns a unique hash code if we do not override the hashCode() method.

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 hash codes, why are they shown equal even though the default hashcode varies?

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 (ie 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.

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().

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

if(oo instanceof Hashvalue)

should be

if (oo instanceof HashValue)

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");
    }
  }

As others have already pointed out it the methods "equals" and the "hashCode" serve different purposes.

From the specification of hashCode method in Object one can infer that:

  • It is that two equal objects should return same integer result when hashCode method is invoked on them 两个相等的对象返回相同的整数结果
  • It is highly recommended that unequal objects return distinct integer values

Your code (taking into consideration the change has proposed) satisfies criteria (a) hence you get the output as "EQUALS". 提出的更改)满足标准(a),因此您将输出视为“EQUALS”。

But is a good practice to follow (b) as this results in better performance when instance of the class are used as hashtable keys. When unequal objects return the same hashCode and if such a class is used as hashtable key, then every object hashes to the same bucket, and hashtable would degenerate to a linkedlist leading to reduced performance.

In the following code:

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 couple of issue: 1. Hashvalue is not recognised by your compiler. It should be "HashValue" 2. hh is out of scope once out of if-block. Hence, compiler error.

You can change your program to following and it will work:

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

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

or you can make it more concise as follows:

 public boolean equals(Object oo) {
     if(oo instanceof Hashvalue && this.x == ((HashValue) oo).x) 
         return true;
     return false;
}
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(){
    return x*17;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM