L'override del metodo hashCode() è strettamente legato all'override di equals(): entrambi i metodi forniscono la base per un utilizzo corretto dell'oggetto in collezioni come HashMap, HashSet, Hashtable e altre strutture che si basano sul confronto e sulle funzioni hash.
Regole:
equals(), è necessario fare l'override anche di hashCode().equals() devono restituire lo stesso hashCode().Objects.hash() o i template dell'IDE, per evitare errori.hashCode() deve restituire lo stesso valore per lo stesso oggetto durante la sua "vita" (se i campi coinvolti in hashCode sono immutabili).class User { private String name; public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof User)) return false; User user = (User) o; return Objects.equals(name, user.name); } public int hashCode() { return Objects.hash(name); } }
Domanda: "Cosa succede se due oggetti diversi secondo equals() restituiscono lo stesso hashCode()? Sarà un errore?"
Risposta: No, non è un errore. Le collisioni degli hash code sono risolvibili e attese — è importante solo che se gli oggetti sono uguali secondo equals, il loro hashCode sia lo stesso. Se oggetti diversi secondo equals restituiscono lo stesso hashCode, le collezioni funzioneranno più lentamente (a causa di un numero maggiore di collisioni), ma in modo corretto.
Storia
In un software finanziario si confrontavano progetti su più campi, ma è stato fatto l'override solo di equals(). Si memorizzavano oggetti in HashSet, si sono verificati duplicati, poiché hashCode() non era stato sovrascritto e funzionava con il valore predefinito (differente per ciascun istanza).
Storia
Nel sistema di contabilità di magazzino, dopo aver apportato modifiche alla logica di business, è stato ampliato equals(), ma si è dimenticati di aggiornare hashCode(). Oggetti con hashCode diversi, ma equals=true, venivano persi in HashMap (non trovati tramite chiave), portando a gravi errori finanziari.
Storia
In un'applicazione web si utilizzavano campi mutabili nel calcolo di hashCode. Quando veniva aggiornata il valore di un campo interno, l'hash cambiava, e l'oggetto veniva "perso" per HashSet/HashMap: non poteva essere trovato o rimosso tramite i metodi standard, portando a perdite di memoria e bug.