2010-06-13 11 views
8

C'è qualche altra ragione per implementare una funzione di codice hash per i miei tipi oltre a consentire un buon uso delle tabelle hash?Quando dovrei definire una funzione di codice hash per i miei tipi?

Diciamo che sto progettando alcuni tipi che intendo utilizzare internamente. So che i tipi sono "interni" al sistema, e so anche che non userò mai quei tipi nelle tabelle hash. Nonostante ciò, decido che dovrò ridefinire il metodo equals().

La teoria dice che dovrei anche ridefinire il metodo del codice hash, ma non vedo alcun motivo per cui, in questo caso, dovrei farlo.

Qualcuno può indicarmi qualsiasi altra ragione?

Questa domanda può essere riformulata in: in cui situazioni dovremmo implementare un metodo di codice hash nei nostri tipi.

PS: Non sto chiedendo come implementarlo. Sto chiedendo quando.

risposta

10

Il numero non è possibile - ma il codice, ad esempio, utilizzerà LINQ? Ci sono un numero di posti inaspettati che potrebbero utilizzare una hashmap o un dizionario sui tuoi dati.

Se non si desidera l'inaspettato ... "divertimento", se si modifica Equals, si sostituisce GetHashCode. Allo stesso modo, qualsiasi IEquatable<T>.Equals deve corrispondere all'implementazione object.Equals.

+0

+1 per "divertimento" imprevisto. Bel giro di parole, Marc! – spender

4

in cui situazioni dovremmo implementare un metodo di codice hash nei nostri tipi.

Risposta breve: Ogni volta che si sostituisce .Equals. Perché le Linee guida sulla progettazione di quadri dicono così.

6

Sì, sicuramente. hashCode e equals sono 2 visualizzazioni sulla stessa cosa e devono essere coerenti. Molte routine nelle Collezioni usano l'hashcode e iniziano a comportarsi male se dice cose diverse da uguali. Puoi leggere 'comportamento anomalo' come 'incredibilmente difficile trovare bachi che portano alla perdita precoce dei capelli'.

Se si esegue l'override di Equals, è necessario Sostituire hashcode, non perché la linea guida lo dice, ma perché si valutano i capelli (o il tempo).

I moderni IDE generano buoni equi/hashcode per te e EqualsBuilder/HashCodeBuilder da Java Commons o Spring possono aiutarti a semplificare. Il progetto Lombok li genera al volo.

Questa è una cosa seria, e il meglio che puoi fare con questi metodi è farlo bene, e ci sono centinaia di modi per sbagliare, portando a dolore e sofferenza. Se puoi evitare di scriverli da solo, fallo su generatori o librerie per aiutarti.

+0

Resharper esegue l'implementazione dell'uguaglianza per la colazione. Punta, clicca clic, vai. – spender

+1

IntelliJ: Alt-Ins (Ctrl-N) + selezionare "Genera Equals/Hashcode" con il cursore + Invio. Eclipse e Netbeans simili. Hanno uno svantaggio: se si usano le metriche del codice, queste routine si manifestano come pasticche a causa della complessità ciclomatica e non sono in grado di seguire tutte le tracce attraverso il codice per esempio. Così creano un ambiente in cui altre routine cattive possono nascondersi. EqualsBuilder/HashcodeBuilder non hanno questo problema. –

+0

* "... ma perché dai valore ai capelli (o al tempo)" *. O vita, se un collaboratore deve sistemare il tuo casino. :-) –

0

Se si è veramente sicuri che i propri oggetti non verranno utilizzati in una tabella hash e tale hashcode non viene utilizzato, è possibile sovrascrivere hashCode per generare un'eccezione "non implementata". Questo è più sicuro che non sovrascrivere poiché proibisce esplicitamente l'uso del metodo ed evita gli errori salienti che altrimenti risulterebbero. Ti mostrerà anche chiaramente se il metodo è effettivamente utilizzato.

Tuttavia, direi che uso l'IDE solo per generare un'implementazione sostenibile che sia coerente con Equals e che venga eseguita con esso.Solitamente i tipi di valore che sovrascrivono sono uguali e durante il test di questi vengono generalmente utilizzate le mappe, quindi è logico implementare il contratto completo richiesto da equals/hashcode api.

Problemi correlati