简体   繁体   English

覆盖Java域类的equal()和hashCode()方法

[英]Overrriding equal() and hashCode() method of domain Class in Java

I have a domain Class named Subscriber and its definition is something like this: 我有一个名为Subscriber的域类,其定义是这样的:

public class Subscriber {
   private long id;
   private String email;
   private String subscriberName;
   private Topic subscribingTopic;

   //other attributes and getters setters.
}

public class Topic{
   private long id;
   private String topicName; //unique
}

My problem is I need to override the equal() and hashCode() methods of this Subscriber class. 我的问题是我需要重写此Subscriber类的equal()和hashCode()方法。 Overriding equal() is somewhat easy task (just comparing basic attributes, in this case there are three of them). 覆盖equal()有点容易(只是比较基本属性,在这种情况下有三个)。 But I am facing problems while overriding hashCode() method. 但是我在覆盖hashCode()方法时遇到了问题。 How I can write hashCode() that I can trust to be used by hibernate safely, while managing my domains. 我如何编写可以信任的hashCode(),以便在管理我的域时可以安全地被hibernate使用。 Can I trust IDE generated one? 我可以信任IDE生成的吗?

Any help will be appreciated and thanks in advance! 任何帮助将不胜感激,并在此先感谢!

If you're on Java 7, you could use Objects.hash() : 如果您使用的是Java 7,则可以使用Objects.hash()

return Objects.hash(email, subscriberName, subscribingTopic);

If you're on Java 6, you could use Guava's Objects.hashCode() method (the same way as above). 如果您使用的是Java 6,则可以使用Guava的Objects.hashCode()方法(与上述方法相同)。

If you're on Java 5, you could use Apache commons-lang HashCodeBuilder class to help you. 如果您使用的是Java 5,则可以使用Apache commons-lang HashCodeBuilder类来帮助您。

You can use IDE like Eclipse to generate hashCode method for you. 您可以使用像Eclipse这样的IDE来为您生成hashCode方法。 One sample hashCode method is below: 下面是一个示例hashCode方法:

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((email == null) ? 0 : email.hashCode());
        result = prime * result + (int) (id ^ (id >>> 32));
        result = prime
                * result
                + ((subscriberName == null) ? 0 : subscriberName.hashCode());
        result = prime
                * result
                + ((subscribingTopic == null) ? 0 : subscribingTopic
                        .hashCode());
        return result;
    }

You need to create a similar hashCode method in Topic class as well. 您还需要在Topic类中创建类似的hashCode方法。

Per Object#hashCode API: 每个Object#hashCode API:

The general contract of hashCode is: hashCode的一般约定为:

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. 在Java应用程序的执行过程中,只要在同一对象上多次调用它,则hashCode方法必须一致地返回相同的整数,前提是未修改该对象的equals比较中使用的信息。 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. 如果根据equals(Object)方法,两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. 根据equals(java.lang.Object)方法,如果两个对象不相等,则不需要在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。 However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables. 但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

Its general practice to use prime number 31 and combine the attribute values in a*31^(x)+b*31^(x-1)+..c to achieve the unique number for the object. 它的一般做法是使用质数31,并在a * 31 ^(x)+ b * 31 ^(x-1)+ .. c中组合属性值以获得对象的唯一编号。 In the process, you can use the hashCode method of underline object. 在此过程中,可以使用下划线对象的hashCode方法。 The above method also does the same. 上面的方法也一样。

How I can write hashCode() that returns unique hash value using the specified three attributes? 如何编写使用指定的三个属性返回唯一哈希值的hashCode()?

It does not have to be unique, only distinct enough to distinguish among non-equal values. 它不必是唯一的,只需足够明显以区分不相等的值即可。

One common way is to use component hash codes, and combine them as ((h1*31)+h2)*31+h3 and so on. 一种常见的方法是使用组件哈希码,并将它们组合为((h1*31)+h2)*31+h3 ,依此类推。

Here is how you do it: first, define hashCode for the Topic , like this: 操作方法如下:首先,为Topic定义hashCode ,如下所示:

int hashCode() {
    return topicName.hashCode()*31 + (int)id;
}

You need to override Topic 's equals as well! 您还需要覆盖Topicequals

Then define the hash code for Subscriber , like this: 然后为Subscriber定义哈希码,如下所示:

int hashCode() {
    return id.hashCode()*31*31*31
         + email.hashCode()*31*31
         + subscriberName.hashCode()*31
         + subscribingTopic.hashCode();
}

The code above assumes that the constructor initializes all components of the Subscriber to be non-null. 上面的代码假定构造函数将Subscriber所有组件初始化为非null。

The hashCode() does not need to be unique. hashCode()不必唯一。 The only thing is that it must return the same hashcodes for obj1 and obj2 , if obj1.equals(obj2) . 唯一的问题是,如果obj1.equals(obj2) ,则必须为obj1obj2返回相同的哈希obj1.equals(obj2) You can just return email.hashCode() for example. 例如,您可以仅返回email.hashCode()

Perfect hash function does not exist - it is not possible to return different hashcodes for every pair of different elements. 完美的哈希函数不存在-无法为每对不同的元素返回不同的哈希码。 Java uses equals for further differentiation(if the hashcodes are the same). Java使用equals进行进一步区分(如果哈希码相同)。

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

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