Perface

  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

Recommended by the author of "Effective Java"

  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 bytecharshort, 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.

 

Overriding hashCode() and equals() using Apache Commons Lang

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

 

 

Automatically generated by eclipse IDE

  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.

 

  

Summary

  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.

 

References

  Working with hashCode and equals methods in java

   Apache Commons Lang

 

posted on 2014-10-24 19:42  转瞬之夏  阅读(438)  评论(0编辑  收藏  举报