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ę.