简体   繁体   English

哈希码和等于

[英]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. equalshashCode方法必须一致,这意味着当两个对象根据equals方法相等时,它们的hashCode方法应该返回相同的哈希值。

Java returns a unique hash code if we do not override the hashCode() method. 如果我们不覆盖hashCode()方法,Java将返回唯一的哈希代码。

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 . 首先,在该行中,您需要将Hashvalue更改为HashValue ,因为您的类实际上称为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. 这不会编译,因为当你最终使用它时, hh不在范围内。

  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. 第一个if语句应该确保在比较两个不是HashValues的东西(即抛出异常)时根本不运行该函数,或者它应该返回false因为HashValues永远不会等于其他类型的对象。 I generally prefer returning false to throwing an exception. 我通常更喜欢返回false来抛出异常。

  3. The second if statement is redundant, because you're just returning what the condition evaluates to. 第二个if语句是多余的,因为您只是返回条件评估的内容。

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. 为了确保所有相等的对象具有相同的哈希代码,你必须覆盖hashCode()HashValue必须确保它不辜负保证。 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 . 实现很简单,因为你的对象只是一个int的包装器。 You'll need to think harder about this as your objects get more sophisticated. 随着对象越来越复杂,你需要更加思考。

Equality is only determined by method equals(). 平等仅由方法equals()决定。 And method hashCode() is used in other situations, like by Map or Set. 方法hashCode()用于其他情况,例如Map或Set。 It is somewhat like a pre-condition or hint before actually calling equals (for efficiency). 在实际调用equals(效率)之前,它有点像先决条件或提示。 So it is assumed that if 2 objects are equal (that is, equals() returns true), then their hashCodes() must return the same value. 因此假设如果2个对象相等(即equals()返回true),则它们的hashCodes()必须返回相同的值。

So in your code, 2 objects are equal, as long as your overriden equals() returns true, no matter what hashCode() does. 所以在你的代码中,2个对象是相等的,只要你的overriden equals()返回true,无论hashCode()是什么。 hashCode() is not called at all when comparing for equality. 在比较相等性时,根本不调用hashCode()。

This question has more in-depth information regarding to the relationship between equals() and hashCode(). 这个问题有关于equals()和hashCode()之间关系的更深入的信息。

For starters, you need to capitalize the v in "Hashvalue" 对于初学者,你需要在“Hashvalue”中大写v

if(oo instanceof Hashvalue)

should be 应该

if (oo instanceof HashValue)

HashValue and Hashvalue are two different identifiers HashValueHashvalue是两个不同的标识符

if(oo instanceof HashValue) works because your class-name is HashValue not Hashvalue if(oo instanceof HashValue)有效的,因为你的类名是HashValue而不是Hashvalue

EDIT : 编辑:

Your code doesn't work because hh isn't in scope when you are using it. 您的代码不起作用,因为当您使用它时, hh不在范围内。

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. 正如其他人已经指出的那样,方法“等于”而“hashCode”用于不同的目的。

From the specification of hashCode method in Object one can infer that: Object中hashCode方法的规范可以推断出:

  • It is required that two equal objects should return same integer result when hashCode method is invoked on them 当对它们调用hashCode方法时, 需要两个相等的对象返回相同的整数结果
  • It is highly recommended that unequal objects return distinct integer values 强烈建议不等对象返回不同的整数值

Your code (taking into consideration the change tgamblin has proposed) satisfies criteria (a) hence you get the output as "EQUALS". 您的代码(考虑到tgamblin提出的更改)满足标准(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. 但是遵循(b)是一种很好的做法,因为当使用类的实例作为哈希表键时,这会带来更好的性能。 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. 当不相等的对象返回相同的hashCode并且如果将这样的类用作散列表键时,则每个对象散列到同一个桶,并且散列表将退化为链接列表,从而导致性能降低。

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. 有几个问题:1。编译器无法识别Hashvalue。 It should be "HashValue" 2. hh is out of scope once out of if-block. 它应该是“HashValue”2。一旦超出if-block,hh就超出了范围。 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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