Wybór języka

Czy hashCode() rekordach w Javie jest jakoś cache'owany?

W czasie moich wykładów, gdy opowiadałem o rekordach w Javie, wielokrotnie padało pytanie: “czy hashCode() w rekordach jest jakoś cache’owany?”. Sprawdźmy to ;-)

W zasadzie, jeśli jesteś już po lekturze mojego poprzedniego wpisu o metodach equals() i hashCode() w rekordach, prawdopodobnie znasz już odpowiedź. Z racji tego, że to osobne pytanie, przeprowadźmy osobny eksperyment.

Najpierw zdefiniujmy prostą metodę do odpluskwiania:

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

Następnie uruchommy ów kod:

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) {
    list.add(word);
    printHashCodes(record, list);
}

Rezultaty, które otrzymuję wykorzystując OpenJDK Runtime Environment (build 16+36-2231) bez żadnych dodatkowych przełączników czy parametrów, są następujące:

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

Jeśli u Ciebie pokazały się inne liczby, nie ma co się martwić. Kontrakt hashCode mówi bowiem, że rezultaty wywołania hashCode() mogą być różne przy każdym uruchomieniu programu napisanego w Javie. Co ma znaczenie, to fakt, że każda zmiana w komponentach rekordu w ramach jednego uruchomienia programu skutkuje innym hashCodem. Jak napisałem poprzednio, rekordy są niezmienne (ang. immutable), lecz jest to niezmienność płytka (ang. shallow immutability).

Odpowiadając na zadane pytanie: nawet jeśli hashCode() jest jakoś cache’owane, to ten cache wygląda na czyszczony po każdej zmianie ;-)

Poza tym JavaDoc jasno stwierdza: Konkretny algorytm, wykorzystany w skrycie dostarczonej implementacji, jest nieokreślony i jest przedmiotem dalszych zmian w zakresie powyższych ograniczeń. Jeśli ciekawi Cię co to za ograniczenia, RTFM!

Poza tym, by uniknąć niedomówień (niektórzy muszą mieć pewne rzeczy napisane wprost): umieszczanie w rekordach komponentów, które są zmienne, to najprawdopodobniej jeden z tych Całkiem Głupich Pomysłów™. Zalecam zastanowić się przynajmniej dwa razy, zanim napiszesz taki rekord. Tutaj chodzi jedynie o demonstrację.

Wybór języka