gogoWebsite

General Java hashCode rewrite solution

Updated to 18 days ago

/chihz/blog/56256


Joshua Bloch, chief Java architect of Google, proposed a simple and general hashCode algorithm in his book "Effective Java".
1. Initialize a shaping variable and assign a non-zero constant value to this variable, such as int result = 17;
2. Select all the domains used for comparison in the equals method, and then calculate the properties of each domain:
(1) If it is a boolean value, then calculate f? 1:0
(2) If it is byte\char\short\int, then calculate (int)f
(3) If it is a long value, calculate (int)(f ^ (f >>> 32))
(4) If it is a float value, then calculate (f)
(5) If it is a double value, calculate (f), and then the result returned is long, and then use rule (3) to process long to get int
(6) If it is an object application, if the equals method adopts the comparison method of recursive calls, then hashCode also adopts the method of recursive calls to hashCode. Otherwise, you need to calculate a paradigm for this domain. For example, when the value of this domain is null, then the hashCode value is 0.
(7) If it is an array, then each element needs to be processed as a separate domain. If you are using JDK version 1.5 and above, there is no need to traverse the array again by yourself. The method includes 8 basic types of arrays and hashCode calculations that reference arrays. The algorithm is the same as above.
Specific implementation of (long[]):

public static int hashCode(long a[]) {
        if (a == null)
            return 0;

        int result = 1;
        for (long element : a) {
            int elementHash = (int)(element ^ (element >>> 32));
            result = 31 * result + elementHash;
        }

        return result;
}

(...) Only has the hashCOde of one-dimensional array elements. If it is a multi-dimensional array, it needs to recursively calculate hashCode, so the (Object[]) method needs to be used.

3. Finally, as above code, merge the hash code of each domain into result: result = 31 * result + elementHash;
4. Test whether the hashCode method complies with the basic principles mentioned at the beginning of the article. Although these basic principles cannot guarantee performance, they can ensure that there is no error.



2. Why do you need to use multiplication to operate result every time? Mainly to make the hash value depend on the order of the domain, or the example above, the final hashCode return values ​​of Test t = new Test(1, 0) are different from Test t2 = new Test(0, 1), t and t2.

3. Why is 31? 31 is a magical number, because any number n * 31 can be optimized by JVM to (n << 5) -n. The operation efficiency of shift and subtraction is much higher than that of multiplication.