I have recently discovered the Objects.hash() method.
My first thought was, that this tidies up your hashCode()
implementation a lot. See the following
Personally I'd side with the short code first, because it is so much quicker to read, change and verify as correct, which all serve to avoid bugs when modifying the class.
Then for performance-critical classes or where fields are costly to hash, I would cache the result (like String
does):
// volatile not required for 32-bit sized primitives
private int hash;
@Override
public final int hashCode() {
// "Racy Single-check idiom" (Item 71, Effective Java 2nd ed.)
int h = hash;
if (h == 0) {
h = Objects.hash(id, timestamp, severity, thread, classPath, message);
hash = h;
}
return h;
}
In this lockless-threadsafe pattern (which assumes an immutable class, naturally) there's a slim chance that hash
might get initialised by different threads multiple times, but this does not matter because the result of the public method is always identical. The key to (memory-visibility) correctness is ensuring that hash
is never written and read more than once in the method.
The array-construction penalty of Objects.hash
might be lower than you imagine once the code gets JIT-inlined & optimised by the C2 compiler. Fortunately the good JDK folks have something baking that should essentially eliminate all the overheads of using it: JEP 348: Java Compiler Intrinsics for JDK APIs
Note that the parameter of Objects.hash
is Object...
. This has two main consequences:
this.id
is converted from long
to Long
.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.
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.
I would like to try and make a strong argument for both.
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.
Joshua Bloch in his book Effective Java, 3rd edition, p. 53 discourages usage of Objects.hash(...)
if performance is critical.
Primitives are being autoboxed and there is a penalty of creating an Object
array.