2015-12-28 37 views
5

Supponiamo di avere una funzione hashcode(), che verrà quindi utilizzata nel nostro metodo equals() per determinare l'uguaglianza di due oggetti. È un approccio consentito/accettato?Si consiglia di utilizzare hashcode per determinare l'uguaglianza in Java?

Supponiamo di utilizzare una semplice implementazione di un codice hash. (Ad esempio alcune variabili di istanza moltiplicate per numeri primi.)

+0

Sta confrontando hashCode l'unica cosa che hai intenzione di fare lì? O solo uno dei tanti passaggi? – Thilo

+0

Non ho intenzione di usarlo, volevo solo lanciarmi l'idea dal momento che il mio istruttore all'unico ha semplicemente detto "non farlo" ma non so spiegare perché. – k4kuz0

risposta

8

Questo è un modo terribile per verificare l'uguaglianza, soprattutto perché gli oggetti non devono essere uguali per restituire lo stesso codice hash.

È necessario utilizzare sempre il metodo di uguale.

La regola generale è:

Se il metodo equals restituisce true per gli oggetti A e B, il metodo hashCode deve tornare lo stesso valore per ae b.

Ciò non significa che se il metodo hashCode per a e b restituisce lo stesso valore, lo stesso valore deve essere restituito true per queste due istanze .

per esempio:

public int hashCode(){ 
    return 5; 
} 

è una valida, sia se è inefficiente, implementazione codice hash.

EDIT:

di utilizzarlo all'interno di un uguale metodo sarebbe qualcosa di simile:

public class Person{ 

private String name; 

public Person(String name){ this.name = name;} 

public String getName(){ return this.name;} 

@Override 
public boolean equals(Object o){ 
    if (!(o instanceof Person)){ return false;} 
    Person p = (Person)o; 
    boolean nameE = this.name == null ? p.getName() == null : this.name.equals(p.getName()); 
    boolean hashE = nameE ? true : randomTrueOrFalse(); 
    // the only moment you're sure hashE is true, is if the previous check returns true. 
    // in any other case, it doesn't matter whether they are equal or not, since the nameCheck returns false, so in best case, it's redundant 
    return nameE && hashE; 
} 

@Override 
public int hashCode(){ 
    int hash = generateValidHashCode(); 
    return hash; 
} 

} 
2

Si tratta di una pessima pratica. Si suppone che gli Hash abbiano una quantità minima di collisioni, ma di solito si hanno più possibilità per gli oggetti rispetto alla quantità di possibili hash e, a causa del principio del pigeonhole, alcuni oggetti distinti devono avere lo stesso hash.

Quando si confrontano gli hash, si ha una certa possibilità di ottenere "falsi positivi".

0

Non fare questo

Se è vero che è necessario sovrascrivere equals() e hashCode() in coppia, avendo lo stesso hash non è lo stesso di avere gli stessi valori.

Metti uno sforzo per pensare veramente alla questione dell'uguaglianza. Non scorciatoia qui ti morderà dopo il.

1

In realtà, non è una cattiva idea!

Ma assicurati di utilizzare questo metodo per determinare la disuguaglianza, non l'uguaglianza. Il codice di hash può essere più veloce di controllare l'uguaglianza, specialmente quando è memorizzato il codice hash (ad esempio in java.lang.String).

Se due oggetti hanno differenti codici hash essi devono essere diverso, altrimenti può essere stesso.Ad esempio si può utilizzare questo metodo come il seguente

Object a, b; 
if(a.hashCode() == b.hashCode()){ 
    if(a.equals(b)) return true; 
} 

return false; 

Essere consapevoli del fatto che in alcuni casi il codice di cui sopra può essere più lento di solo equals() utilizzare, soprattutto quando nella maggior parte dei casi a fa uguale b.

Dalla documentazione di Object.java:

  • se due oggetti sono uguali secondo il metodo equals(Object), quindi chiamando il metodo hashCode su ciascuno dei due oggetti devono produrre lo stesso risultato intero.
  • Non è necessario che se due oggetti non sono uguali secondo il metodo equals(java.lang.Object), quindi chiamare il metodo hashCode su ciascuno dei due oggetti deve produrre risultati interi distinti. Tuttavia, il programmatore dovrebbe essere consapevole del fatto che la produzione di risultati interi distinti per oggetti non uguali può migliorare le prestazioni degli hashtables.
+0

Se si esegue il caching di hashCode, questa è una buona ottimizzazione. In caso contrario, il calcolo dell'hashCode è probabilmente più lento rispetto al confronto di tutti i campi in esso contenuti. – Thilo

+0

Poiché ciò potrebbe causare falsi positivi, non lo definirei "non una cattiva idea". Sarebbe valido solo se lo aggiungi come controllo aggiuntivo, ma in sostanza quello che stai facendo è: if (allIsTrue && (allIsTrue || somethingSimilar)) quindi, in pratica: allIsTrue ha già risposto alla domanda – Stultuske