2012-07-01 19 views

risposta

3

Tecnicamente, non è necessario sovrascrivere il metodo hashCode finché gli oggetti uguali hanno lo stesso hashCode.

Quindi, se si utilizza il comportamento predefinito definito da Object, dove equals restituisce solo true solo per la stessa istanza, non è necessario sovrascrivere il metodo hashCode.

Ma se non si esegue l'override dei metodi equals e hashCode, significa che è necessario assicurarsi di utilizzare sempre la stessa istanza chiave.

Es .:

MyKey key1_1 = new MyKey("key1"); 

myMap.put(key1_1,someValue); // OK 

someValue = myMap.get(key1_1); // returns the correct value, since the same key instance has been used; 

MyKey key1_2 = new MaKey("key1"); // different key instance 

someValue = myMap.get(key1_2); // returns null, because key1_2 has a different hashCode than key1_1 and key1_1.equals(key1_2) == false 

In pratica si ha spesso una sola istanza della chiave, quindi tecnicamente non è necessario sovrascrivere i metodi equals e hashCode.

Ma è delle migliori pratiche per ignorare i metodi equals e hashCode per le classi utilizzate come chiavi in ​​ogni caso, perché qualche tempo dopo voi o un altro sviluppatore potrebbe dimenticare che la stessa istanza deve essere utilizzato, che può portare alla difficile tenere traccia dei problemi.

E nota: anche se si sostituiscono i metodi equals e hashCode, è necessario assicurarsi di non modificare l'oggetto chiave in un modo che cambierebbe il risultato dei metodi equals o hashCode, altrimenti la mappa ha vinto ' trovare il tuo valore più Ecco perché è consigliabile utilizzare oggetti immutabili come chiavi, se possibile.

3

L'unica volta che non c'è bisogno di ignorare la funzione hashCode() è quando anche voi non ignorare equals, in modo da utilizzare il valore predefinito Object.equals definizione di uguaglianza di riferimento. Questo può o non può essere quello che vuoi - in particolare, gli oggetti diversi saranno non essere considerati uguali anche se hanno gli stessi valori di campo.

Se si ignora equals ma non hashCode, sarà indefinito HashMap comportamento (leggi: non farà alcun senso a tutti, e sarà totalmente danneggiati).

4

Se non si esegue l'override di hashCode AND equivale, si otterrà il comportamento predefinito in base al quale ogni oggetto è diverso, indipendentemente dal suo contenuto.

+2

A meno che non stia estendendo qualcosa che ha un hashCode che funziona per lui – Miquel

2

Dipende dalla classe dell'oggetto utilizzata come chiave. Se è una classe personalizzata come la tua proposta, e non estende nulla (cioè estende Object) la funzione hashCode sarà quella di Object, e che prenderà in considerazione i riferimenti di memoria, rendendo due oggetti che hanno lo stesso aspetto per te hash codici diversi.

Quindi sì, a meno che non si stia estendendo una classe con una funzione hashCode() che sai funzionare per te, è necessario implementare la tua. Assicurati anche di implementare equals(): alcune classi come ArrayList utilizzeranno solo eguali mentre altre come HashMap controlleranno sia su hashCode() e su equals().

+0

Hai assolutamente ragione. Ho appena controllato HashMap.put() per essere sicuro, e in effetti avevo sbagliato. Grazie! Ho corretto la risposta per riflettere il tuo commento. – Miquel

+1

Senza verificare i dettagli di implementazione, è possibile vedere che a livello astratto deve essere dovuto all'inevitabilità delle collisioni di hash. Qualsiasi due oggetti in collisione su un hashcode finirebbe lo stesso se non fosse considerato "uguale". –

0

Considera anche che se la tua chiave non è immutabile potresti avere problemi. Se si inserisce una voce con una chiave mutabile nella mappa e si modifica in seguito la chiave in un modo che influisce su hashcode e equivale a perdere la voce nella mappa, in quanto non sarà più possibile recuperarla.

0

È necessario eseguire l'override dei metodi equals() e hashCode() dalla classe Object. L'implementazione predefinita di equals() e hashcode(), che sono ereditati dallo java.lang.Object, utilizza la posizione di memoria di un'istanza dell'oggetto (ad esempio [email protected]). Ciò può causare problemi quando due istanze di un oggetto hanno le stesse proprietà ma l'ereditato equals() restituirà false perché utilizza lo memory location, che è diverso per le due istanze.

Anche il metodo toString() può essere sovrascritto per fornire una rappresentazione stringa corretta del proprio oggetto.

considerazioni principali quando si implementa un utente definito chiave

  1. Se una classe sostituisce equals(), deve sostituire hashCode().
  2. Se 2 oggetti sono uguali, anche i loro valori hashCode devono essere uguali.
  3. Se un campo non viene utilizzato in equals(), non deve essere utilizzato in hashCode().
  4. Se si accede spesso, hashCode() è un candidato per la memorizzazione nella cache per migliorare le prestazioni.
Problemi correlati