Language selector

Is hashCode() in Java records cached?

Many times during my talks covering Java records I was asked if the result of hashCode() of a record is cached. Let’s see. ;-)

Actually, if you have followed my previous post on record’s equals() and hashCode(), you may already know the answer. But since this question is separate, let’s run a separate experiment.

First, let’s define a simple debug method:

static void printHashCodes(Record record, List<?> list) {
    System.out.printf("%d, %d, %s%n", record.hashCode(), list.hashCode(), list);

Next, let’s run the following:

record IsHashCodeCached(List<?> list) {}
var list = new ArrayList<String>();
var record = new IsHashCodeCached(list);
var words = List.of("ene", "due", "like", "fake");
printHashCodes(record, list);
for (String word : words) {
    printHashCodes(record, list);

The results I get using OpenJDK Runtime Environment (build 16+36-2231) without any extra switches or parameters are the following:

1, 1, []
100603, 100603, [ene]
3218521, 3218521, [ene, due]
103095902, 103095902, [ene, due, like]
-1095859017, -1095859017, [ene, due, like, fake]

If you don’t get the very same numbers, don’t worry. The contract of hashCode says that the results of hashCode() might differ when re-starting a given Java programme again and again. What matters here is that the hashCode on a record changes whenever we change one of its components during single programme execution. As I wrote in the previous post, records are immutable, but it’s shallow immutability.

Answering the original question: even if hashCode() is cached somehow, this cache seems to be invalidated after every change. ;-)

Besides, the JavaDoc clearly states: The precise algorithm used in the implicitly provided implementation is unspecified and is subject to change within the above limits. If you’re interested in the limits, RTFM!

Apart from that, to be extra clear (some need to have things written directly): having mutable components in records might be one of these Really Bad Ideas™. I suggest thinking at least twice before such a record is written. This post is just a demo.

Language selector