Equals method and Hashcode method

Source: Internet
Author: User
Tags wrapper

From http://blog.sina.com.cn/s/blog_4a5ca024010008tj.html below is the text

Xiao Cui's translation of Virgo "Equals method and Hashcode method" (2007-06-22-21:04:42

Cui (folk also called Tri, namely CY, see chat Record series), Hunan people, more than 20 years old, unmarried. Once aj*q*051 class team leader, the existing translation of the "Equals method and Hashcode method", in this blog starting, we welcome.

Equals Methods and hashcode Method

Author: Manish Hatwalne

Original address: http://www.geocities.com/technofundo/tech/java/equalhash.html

Preface

In the Java language, there are two very important methods in the parent class Java.lang.Object of all classes.

· public boolean equals (Object obj)

· public int hashcode ()

The importance of these two methods is reflected when the user class is compared to other classes or is added to the collection. These two methods have become the subject of SCJP 1.4 certification. This article will provide you with the necessary information about these two methods for people who are interested in SCJP 1.4, even if you are not interested in this certification, and can help you understand the mechanisms of these two methods and implement them in your own classes.

Public Boolean equals (Object obj)

This method is used to determine whether the object calling the equals method is equal to the other objects passed in as arguments. The default implementation of the equals method in the object class is simply to determine whether x = y is valid if the reference x and Y of two objects point to the same object. This particular comparison is "shallow comparison". However, the class that implements the equals method should implement a "deep comparison", that is, to compare the corresponding data content. Because there are no attributes in the Object class, a simple implementation is done using "shallow comparison."

The following is a contract for the Object class equals method in the JDK 1.4 API documentation:

Indicates whether a different object is "equal" to this object.

The Equals method (on a Non-empty object reference) implements the equality relationship:

· Reflexivity: Should return true for any (non-null) reference value X,x.equals (x).

· Symmetry: For any (non-null) reference value x and Y, x.equals (y) should return true if and only if Y.equals (x) returns True.

· Transitivity: For any (non-null) reference value x, Y, and Z, if X.equals (y) returns true and Y.equals (z) returns True, then X.equals (z) should return true.

· Consistency: For any (non-null) reference value x and Y, multiple calls to X.equals (Y) always return TRUE or always return false, provided that the information used in the Equals comparison on the object has not been modified.

· False should be returned for any non-null reference value x,x.equals (null).

The Equals method of the object class implements the equality relationship with the greatest difference probability on an object; that is, for any non-null reference value x and Y, this method returns True if and only if X and Y refer to the same object (x = = Y has a value of true).

Note: When this method is overridden, it is often necessary to override the Hashcode method to maintain the general contract for the Hashcode method, which declares that the equality object must have an equal hash code.

The contract of the equals method just describes its needs, and once you fully understand it, it becomes very easy to implement this method correctly. Now let's analyze the true meaning of each article.

1. reflexivity- It simply describes that in any case an object must equal itself. Unless you deliberately implement the equals method in a different way.

2. symmetry- If the object of a class is equal to the object of another class, then the object of the other class must also be equal to the object of the class. In other words, an object cannot unilaterally determine that it is equal to another object. Therefore, two objects belonging to two classes must determine whether they are equal in two ways. The two must be consistent. Therefore, it is inappropriate and incorrect to compare the equals method in your own class with the objects of the java.lang.String class or other Java built-in classes. It is important to fully understand this because an improper implementation of the equals method is likely to violate this rule and lead to an unexpected result.

3. transitivity- The first object equals the second object and the second object equals the third object, then the first object is equal to the third object. In other words, if two objects are equal, according to the symmetry principle, one of them cannot determine that it equals another object of different types. All three different permutations and combinations must follow the principle of symmetry. Take a look at this example, A,b,c is three classes. Both A and B implement the equals method in such a way: the methods of comparing classes A and Class B objects. Now, if the author of Class B decides to modify his equals method, the new implementation method can also be compared to the C class, and then he will violate the delivery principle. Because there is no suitable comparison method in object A and Class C.

4. Consistency – if two objects are equal, so long as they are not modified, they must maintain this equality relationship. Similarly, if they are not equal, as long as they are not modified, they will also maintain this unequal relationship. Such modifications may occur either or both of them are modified.

5. compared to null- the object of any class is not equal to NULL, so theequals method must return False when NULL is passed in as a parameter of the equals method. You have to make sure that the equals method you implement should return FALSE when NULL is passed as an argument to the equals method.

6. The relationship between Equals and hash codes – the final note of the API document is important and describes the relationship between the two methods. It shows that if two objects are equal, they must have the same hash code. However, the converse proposition is not tenable. This is discussed in detail later in this article.

public int hashcode ()

This method returns the hash code value of the object that called the method. This method returns the hash code value of the integer form, and the collection based on the hash method uses the return value, such as Hashtable, HashMap, HashSet, and so on. This method must also be overridden if the equals method is overridden.

The following is a statement about the Object class Hashcode method in the JDK 1.4 API documentation:

Returns the hash code value for this object. Support for this method is to provide some advantages for the hash table, for example, Java.util.Hashtable provided by the Hashtable.

Hashcode's conventional agreements are:

· During Java application execution, when the Hashcode method is called more than once on the same object, the same integer must be returned consistently, provided that the information used in the Equals comparison on the object has not been modified. The integer does not need to be consistent for another execution from one application to the same application.

· If two objects are equal according to the Equals (object) method, then calling the Hashcode method on each object in two objects must produce the same integer result.

· The following conditions are not required: If two objects are not equal according to the Equals (Java.lang.Object) method, then calling the Hashcode method on either of the two objects must produce a different integer result. However, programmers should know that generating different integer results for objects that are not equal can improve the performance of the hash table.

In fact, the Hashcode method defined by the object class does return different integers for different objects. (This is typically done by translating the object's internal address into an integer, but the JAVATM programming language does not require this implementation technique.) )

The agreement of theHashcode method is relatively simple and easy to understand compared to the agreement of the equals method. It declares two important conditions for implementing the Hashcode method. The 3rd agreement is in fact the 2nd detailed description. Next, understand the meaning of the agreement.

1. consistency in the same execution- first, the contract declares that the hash code returned by the Hashcode method must always be repeated in the same execution of the application, as long as the object affects equals The information for the method has not been modified.

2. the relationship between hash code and equals- the 2nd in the agreement is that the hashcode method is necessary for the equals method. It only emphasizes the same relationship--the same object must contain the same hash code. The 3rd detailed description of objects that are not equal does not necessarily require a different hash code.

After reviewing the common conventions of both methods, you can use the following statement to clearly outline the relationship between the two.

objects that are equal must have the same hash code, and objects that are not equal do not necessarily need to have different hash codes.

The remaining treaties in the two methodological conventions do not directly relate to the relationship between the two methods. Those treaties have been discussed before. This relationship also underscores the need to override the Hashcode method whenever you rewrite the equals method. If you do not follow this Convention, the use of Java collection classes or other classes often leads to uncertain, unexpected results.

the right implementation example

The following code shows how to fully implement theequalsMethods andhashcodemethod so that it can coordinate with other Java classes to work properly. of this classequalsMethod uses andStringImplemented in similar ways as Java built-in types or wrapper classes: Provides comparisons to objects of the same type. public class test{    private int num;     private  String data;       public boolean equals (object obj) {         if (this == obj)              return true;         if ((obj == null)  | |   (Obj.getclass ()  != this.getclass ())              return false;         //  Here the Parameter object is test type          Test test =  (Test) obj;         return num == test.num &&  ( data == test.data | |   (data != null && dAta.equals (Test.data)));    &NBSP}     public int hashcode () {         int hash = 7;         hash = 31 * hash + num;         hash = 31 * hash +  (null ==  data ? 0 : data.hashcode ());         return hash;    &nbsp     //  Other methods} 

Now, explain why this implementation is the correct implementation. The test class contains two member variables: NUM and data. These two variables define the properties of the object and participate in the comparison of objects of that class. Therefore, these two variables should also be involved in the computation of object hash codes.

First look at the equals method. On line 8th, we can see the object being passed in (as a parameter) compared to itself. If a reference to two objects points to the same object in the heap area, this decision can save a lot of time when the cost of comparing operations is very expensive. Next, the If condition on line 10th determines whether the parameter is NULL, if not NULL, and then (or the operator | | is a short-circuit judge. Checks whether the parameter is of type types by comparing the type of the Parameter object and the type of the current object. Gets the type of the current reference by calling GetClass (). If either condition is not met, the method returns false. The code is as follows:

if ((obj = null) | | (Obj.getclass ()!= This.getclass ())) return false; // Recommended
This condition should be judged as the preferred, not the following:

if (!) ( obj instanceof Test) return false; // Avoid

This is because when the argument is a subclass of the test class, the first conditional expression is judged (the blue code) to make sure that it returns false. However, the second conditional expression judgment (red code) will be faulted. If the argument is a subclass of the test class, the judgment containing the instanceof operator will not return false. Therefore, it may violate the symmetry principle in the agreement. Instanceof This comparison is likely to occur in a variety of situations, one that cannot be transformed into subclasses and throws an exception, the other being that private members of the parent class cannot be used in subclasses and therefore cannot be compared. But if the class is final, then the instanceof check is correct, because that class will not have subclasses. The first conditional expression check can work correctly in a final type or a class that is not final. Note that if the parameter is null, both of these conditions return false. If the expression to the left of the OR operator is the null,instanceof operator returns false without considering the expression to the right of the operator. This is specified in the Java language Specification JLS 15.20.2. In any case, the first condition-expression check will be the preferred type check.

The equals method implemented by this class provides only a comparison of objects of the same type. Note that this is not mandatory. However, if a class provides a way to compare with other types of objects, other types of classes should also provide a method of comparison with this class, in order to fulfill the symmetry and reflexivity principles in the Convention. The exact implementation of the equals method should not violate the requirements of both parties. Lines 14th and 15th actually show a comparison of the member variable data, which returns true if the value is the same. Line 15th also ensures that null pointer exceptions do not occur when you execute a string-type Equals method.

When implementing the equals method, you can simply use the = = operator For comparison after some necessary transformations. (for example, a comparison between float and float.floattointbits or double and double.doubletolongbits.) However, comparisons between object references cause them to be recursive in the equals method. You also need to make sure that null pointer exceptions are not thrown when calling their equals method.

Here are some guidelines for how to implement the equals method correctly.

1. If the parameter is a reference type, use the = = operator for comparison. If equality returns TRUE. Doing so will save you time when the cost of comparison is very expensive.

2. Use the following conditional expression to determine whether the parameter is null and whether the type is appropriate. False is returned if the condition is not satisfied.
if ((obj = null) | | (Obj.getclass ()!= This.getclass ())) return false;
Note that the appropriate type does not imply the same type or the type in the code example. It can be any type or interface that provides a comparison method.

3. Converts the parameter type to the appropriate type. To put it another way, the appropriate type may not be of the same type. Similarly, because of the type check expression above, this step does not result in a type conversion exception.

4. Compares the parameter object to be equal to the important variable in the current object, and returns False if all conditions are true. As mentioned earlier, when comparing a member or variable of a class, a variable of the base type can be compared directly to a variable with the necessary conversion (for example, Float and float.floattointbits or double to Double.doubletolongbits). However, comparisons between object references cause them to be recursive in the equals method. You also need to make sure that null pointer exceptions are not thrown when calling their equals method. Just as you did in the example code in line 15. It is neither necessary nor advisable to include in the comparison those member variables computed from other variables. This guarantees the performance of the equals method. It is only up to you to decide which of the members of the class is important and which is not.

5. Do not change the parameter type of the equals method, it must use Java.lang.Object as the parameter type, instead of using your custom type. If you change the parameter type, you will not override the equals method but overload the method. This common mistake can lead to many problems. Because this is not a compile error, it can be difficult to find a solution to your problem when your code doesn't work properly.

6. Review your equals method to see if it all implements all the conventions of the equals method.

7. Finally, when you rewrite the equals method, don't forget to rewrite the hashcode method, which is an unforgivable mistake. ;)

Now, look at the hashcode method in the example. In line 20 of the code, a Non-zero constant of 7 (arbitrary) is assigned to the variable hash. Because the class's member variable num and data participate in the comparison in the equals method, they should also be introduced in the calculation of the hash code. This is not mandatory, though. You can also improve the performance of the Hashcode method by using a subset of the variables that are involved in calculating the equals method. The performance of the Hashcode method is really important, but you also have to be careful about selecting this subset. This subset should contain those variables that are most likely to produce the maximum variance value. Sometimes, using all variables that participate in the equals method makes the hash code more meaningful to compute. The class in the example code uses the two variables, num and data, to compute the hash code. The 21 lines and 22 lines in the code compute the hash code based on these two variables. Line 22nd also ensures that when the hashcode method is executed, a null pointer exception is not caused if the data variable is null. This implementation ensures that there are no conventions that violate the hashcode method. This implementation returns a consistent hash code value when the hashcode method is called more than once, and guarantees that equal objects return the same hash code. When the Hashcode method is implemented, the hash code value can be computed directly using the base type after the necessary transformations. such as float and float.floattointbits or double and double.doubletolongbits. Because the hashcode method must return an int, the value of the long type must be converted to an integral type. As for the hash code of the reference type, the hashcode method that invokes the objects can be computed. You should make sure that the hashcode method that invokes the reference type does not cause null pointer exceptions. Writing an excellent hashcode method implementation is not an easy task, and its computed hash code should be evenly distributed, which may require the participation of mathematicians and computer scientists. However, you can also write a fairly good implementation by following simple rules.

The following is a list of guidelines for the correct implementation of Hashcode methods.

1. Set any nonzero integer (for example, 7) for the integer variable hash.

2. When calculating the hash code of an object, you need to include a variable that participates in the calculation of the equals method. To compute a separate hash code var_code for each variable var, the following rules should be followed-

A. If the variable var is byte,char,short or int, then Var_code = (int) var;

B. If the variable var is a long type, then Var_code = (int) (var ^ (var >>> 32));

C. If the variable var is Float, then Var_code = Float.floattointbits (Var);

D. If the variable var is a double type, then
Long bits = Double.doubletolongbits (VAR);
Var_code = (int) (bits ^ (bits >>> 32));

E. If the variable var is boolean, then Var_code = var? 1:0;

F. If variable var is a reference type, first check if it is null, if Null,var_code = 0; Otherwise, the hashcode method that executes the reference type gets the hash code. The simple instance code is as follows:
Var_code = (Null = = var? 0:var.hashcode ());

3. The hash code Var_code of these individual variables is combined with the original hash code variable hash as follows:
hash = * hash + var_code;

4. Follow these steps to compute the hash code value of an important variable in an object and finally return the result hash of the integer

5. Finally, check your hashcode method and confirm that the equality object will return the same hash code value. Also verifies that the hash code value returned by multiple calls to the Hashcode method repeatedly on the same object in the same run is the same.

The policy presented here is only a guide, not an absolute norm. But following these guidelines to achieve these two methods does produce the right and consistent results.

Summary and Tips

· As long as two objects are equal, the two equal objects should contain the same hash code. However, objects that are not equal do not necessarily have different hash codes.

· Unlike the = = Operator's "Shallow comparison", the equals method implements a "deep comparison" by checking whether two objects are logically equal.

· The equals method in the Java.lang.Object class still provides only the same "shallow comparison" as the = = operator.

· The equals method uses a Java object type as an argument rather than a base type. Using a base type when calling the equals method will result in a compilation error.

· Passing in different reference types when calling the equals method does not result in compilation errors or Run-time errors.

· For java.lang.String classes or standard Java wrapper classes, False is returned if the equals method is used and the parameter type differs from the type of the equals method object.

· The Java.lang.StringBuffer class does not overwrite the equals method of the Java.lang.Object class, which inherits the implementation of the Java.lang.Object class.

· The equals method you implement cannot be compared with any Java built-in type, because that would violate the symmetry principle in the equals method contract.

· If the equals method passes in a null argument, the return value is false.

· An object with the same hash code value does not imply that the two objects are equal.

· return 1; This is a legitimate hashcode method Implementation, however this is a very not recommended implementation. It is legitimate only because it ensures that equal objects contain the same hash code, ensuring that multiple calls in the same run return a consistent hash code. Thus it does not violate the general convention of the Hashcode method. It is a bad implementation because it returns the same hash code for all objects. This description applies to all hashcode methods that return the same integer value.

· In the standard JDK 1.4 version, the following several packaging classes Java.lang.Short, Java.lang.Byte, Java.lang.Character and Java.lang.Integer Classes are simply returned as hash codes with their corresponding integer values.

· Starting with JDK version 1.3, the Java.lang.String class caches its hash code, computes only one hash code and stores it in an integer variable, which is returned directly the next time the hashcode method is called. This is legal because the java.lang.String is designed to be immutable.

· It is not correct to include a random number when calculating the hash code value of an object because its multiple invocations in the same run do not return a consistent hash code.

Review Exercises

A few useful review questions- point this

Resource List

If you want to learn more about the details of these two methods, this list will help you.

· Object class-java.lang.object the API documentation for the class. The common conventions for these two methods can be found here.

· A good book effective Java-joshua Bloch. The third chapter of this book in PDF format can be obtained online. This chapter deals with all the methods of the Java.lang.Object class. It also discusses in detail the implementation of the equals method and the hashcode method, the correct and incorrect method, and so on. Part of this article is derived from the information provided in this book. However, this article attempts to explain the mechanism and implementation details of these two methods through some concise examples. It also provides some skills and review questions that help to understand.

· Javaworld article– This article discusses the related methods of the Java.lang.Object class, and also explains the disadvantages of using instanceof conditional expressions in the equals method.

· Importance of Equals and hashcode– this FAQ about the importance of properly overwriting the equals method and the hashcode method. It also mentions the importance of these two methods in the Java set framework.

· Equals & Hash Code Mock test– If you are interested in the small test of these two methods.

· Equals and Hash Code cartoon– a comic strip I created, trying to use illustrations to explain the relationship between the equals method and the hashcode method.

· whizlabs Java Certification (SCJP 1.4) Exam Simulator -explains in detail the questions about the equals method and the hashcode method. There are some other SCJP 1.4 questions.

Thanks :)

In order to make this article as accurate as possible, it has been revised several times. Thanks to Valentin Crettaz and Javaranch's friends for their suggestions for revision. In particular, thanks to Valentin, he points out that using a instanceof conditional expression in the equals method violates the principle of symmetry. If you find any ambiguity or error in the flops, please contact me. Your response will help improve the quality of this article.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.