Use Objects.hash() or own hashCode() implementation?

I would like to try and make a strong argument for both.

Opening disclaimer

For this answer, Objects.hash(), Objects.hashCode(), and any function provided by any library that performs this role are interchangeable. First, I would like to argue, use Objects.hash() or don't use the static Objects functions at all. Any argument for or against this method requires making assumptions about the compiled code that are not guaranteed to be true. (For example, the compiler optimizer may convert the function call into an inline call, thus bypassing the extra call stack and object allocation. Just like how loops that do nothing useful don't make it to the compiled version (unless you turn off the optimizer). You also have no guarantee that future Java versions won't include the JVM version like C# does in it's version of this method. (for security reasons I believe)) So the only safe argument you can make regarding using this function, is that it is generally safer to leave the details of a proper hash to this function than to try to implement your own naive version.

For Objects.hash

  • Guaranteed to be a good hash.
  • Takes 5 seconds to implement.
  • Yours would have had a bug in it (somehow especially if you copy-pasted the implementation)

Against Objects.hash

  • The Java docs make no promises about hash cross-compatibility (Will a JVM v6 and JVM v8 give the same values? always? across OS?)
  • The thing about hashCodes, They work best if "evenly distributed". So if an int value is only valid for range 1 to 100, you might want to "redistribute" its hash-codes to not all be part of the same bucket.
  • If you have any requirement that makes you question how Objects.hash works, reliability/performance wise, Think carefully if the hash-code is really what you want, and implement a custom hash-coding method that addresses your needs.

Following is implementation of Objects.hash - which is calling Arrays.hashCode internally.

public static int hash(Object... values) {
    return Arrays.hashCode(values);
}

This is implementation of Arrays.hashCode method

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

    int result = 1;

    for (Object element : a)
        result = 31 * result + (element == null ? 0 : element.hashCode());

    return result;
}

So I agree with @Andy The cost of creating of these "unnecessary" objects may add up if hashCode is called frequently. If you are implementing yourself it would be faster.


Note that the parameter of Objects.hash is Object.... This has two main consequences:

  • Primitive values used in the hash code calculation have to be boxed, e.g. this.id is converted from long to Long.
  • An Object[] has to be created to invoke the method.

The cost of creating of these "unnecessary" objects may add up if hashCode is called frequently.

Tags:

Java

Hash