Written hashCode
- Store a non-zero constant value, such as 17, in the variable int result.
- For each key field f in the object, complete the following steps:
- A. Calculate the hash code of type int for the field c:
- I. If the field is of Boolean type, calculate f? 1-0.
- Ii. If the field is of type byte, char, short, or int, calculate (int) f.
- Iii. If the field is of type long, compute (int) (f ^ (f >>> 32)).
- Iv. If the field is of type float, float.floattointbits (f) is computed.
- V. If the field is of type double, double-.doubletolongbits (f) is evaluated, and then the hash value for the resulting value of type long is computed as in Step 2.a.ii.
- Vi. If the field is an object reference, and the equals method of the class compares the field by recursively calling equals, it also recursively calls hashCode for the field.
- Vii. If the field is an array, each element is treated as a separate field. That is, apply the above rules recursively, compute a hash code for each important element, and then combine the hash values as described in Step 2.b. If every element in an array domain is important, you can use the arrays.hashcode method.
- B. Merge the hash code c calculated in Step 2.a into result according to the following formula. result = 31 * result + c;
- Returns the result
- After writing the hashCode method, ask yourself if “equal instances have equal hash codes.” Write unit tests to verify your inferences. If equal instances have different hash codes, find out why and fix the error.
Select the number 31 as the multiplier
- 31 can be optimized by the JVM, 31 * I = (I << 5) -i.
- If a prime number is too small, the hash value calculated is not high, which increases the probability of hash conflicts.
- If too large a prime number is selected, the hash value calculated is too high. If the hash value is represented by an int, the result will overflow and the value information will be lost.
- Choosing an even number is equivalent to doing a left shift and wasting space for odd numbers.
- If 31 is selected, the calculated hashCode value is medium and the hash distribution is uniform.
HashCode to equals
- To override equals, you must override hashCode.
- Equlas comparison, objects are equal, hashCode must have the same value.
- HashCode is equal. Two objects are not necessarily equal.
- HashCode is not equal, the two objects must not be equal.
Issues that need attention
- When using hashMap, if the key is a custom Object, then you must override equals and hashCode. Otherwise, hashMap uses the hashCode and equals methods of Object. Using the Object method still yields two different objects, which results in the hashMap still storing both objects, when we only want to store one.
- It is important to note that Lombok @data generates hashCode with looping dependent objects that can cause an infinite loop, which can cause memory leaks, because Lombok’s @data annotation needs to be used with caution.