In the former chapter, I talk about topics about hashCode, And I will continue to finish the introduction to hashCode(). In this chapter, I will recommend several ways to overrwrite hashCode() to facilitate our work
Ideally, a hash function should distribute any reasonable collection of unequal instances uniformly across all possible hash values. Here is a simple recipe:
1. Store some constant nonzero value, say, 17, in an int variable called result.
2. For each significant field f in your object (each field taken into account by the equals method, that is), do the following:
a. Compute an int hash code c for the field:
i. If the field is a boolean, compute (f ? 1 : 0).
ii. If the field is a byte, char, short, or int, compute (int) f.
iii. If the field is a long, compute (int) (f ^ (f >>> 32)).
iv. If the field is a float, compute Float.floatToIntBits(f).
v. If the field is a double, compute Double.doubleToLongBits(f), and then hash the resulting long as in step 2.a.iii.
vi. If the field is an object reference and this class’s equals method compares the field by recursively invoking equals, recursively invoke hashCode on the field. If a more complex comparison is required, compute a “canonical representation” for this field and invoke hashCode on the canonical representation. If the value of the field is null, return 0.
vii. If the field is an array, treat it as if each element were a separate field. If every element in an array field is significant, you can use one of theArrays.hashCode methods.
b. Combine the hash code c computed in step 1) into result as follows:
result = 31 * result + c;
3. Return result.
Apache commons provide two excellent utility classes for generating hash code and equals methods. Below is its usage:
1 import org.apache.commons.lang3.builder.EqualsBuilder; 2 import org.apache.commons.lang3.builder.HashCodeBuilder; 3 public class Employee 4 { 5 private Integer id; 6 private String firstname; 7 private String lastName; 8 private String department; 9 public Integer getId() { 10 return id; 11 } 12 public void setId(Integer id) { 13 this.id = id; 14 } 15 public String getFirstname() { 16 return firstname; 17 } 18 public void setFirstname(String firstname) { 19 this.firstname = firstname; 20 } 21 public String getLastName() { 22 return lastName; 23 } 24 public void setLastName(String lastName) { 25 this.lastName = lastName; 26 } 27 public String getDepartment() { 28 return department; 29 } 30 public void setDepartment(String department) { 31 this.department = department; 32 } 33 @Override 34 public int hashCode() 35 { 36 final int PRIME = 31; 37 return new HashCodeBuilder(getId()%2==0?getId()+1:getId(), PRIME). 38 toHashCode(); 39 } 40 @Override 41 public boolean equals(Object o) { 42 if (o == null) 43 return false; 44 if (o == this) 45 return true; 46 if (o.getClass() != getClass()) 47 return false; 48 Employee e = (Employee) o; 49 return new EqualsBuilder(). 50 append(getId(), e.getId()). 51 isEquals(); 52 } 53 }
In the official doucment of HashCodeBuilder, it describes as follow:
This class enables a good hashCode
method to be built for any class. It follows the rules laid out in the book Effective Java by Joshua Bloch. Writing a good hashCode
method is actually quite difficult. This class aims to simplify the process.
The following is the approach taken. When appending a data field, the current total is multiplied by the multiplier then a relevant value for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then appending the integer 45 will create a hashcode of 674, namely 17 * 37 + 45.
All relevant fields from the object should be included in the hashCode
method. Derived fields may be excluded. In general, any field used in the equals
method must be used in the hashCode
method.
To use this class write code as follows:
public class Person { String name; int age; boolean smoker; ... public int hashCode() { // you pick a hard-coded, randomly chosen, non-zero, odd number // ideally different for each class
return new HashCodeBuilder(17, 37). append(name). append(age). append(smoker). toHashCode(); } }
if you are using any code editor, they also must be capable of generating some good structure for you. For example, Eclipse IDE has option under right click on class >> source > Generate hashCode() and equals() … will generate a very good implementation for you.
In general, it is not common to override the hashCode() method, but if we need to do it in practical work, it will be a troublesome experience. To make our work easier and more efficiently, it is a good idea to follow the recommendations in the chapter. But if you want to achieve a higher performance, you'd better to override the method yourself carefully.
Working with hashCode and equals methods in java