2013-04-17 31 views
25

Ho due oggetti java che vengono istanziati dalla stessa classe.Come confrontare due oggetti java

MyClass myClass1 = new MyClass(); 
MyClass myClass2 = new MyClass(); 

Se ho impostato entrambi i loro oggetti da esattamente lo stesso valore e quindi verificare che essi sono la stessa

if(myClass1 == myClass2){ 
    // objects match 
    ... 

} 

if(myClass1.equals(myClass2)){ 
    // objects match 
    ... 

} 

Tuttavia, nessuno di questi approcci restituiscono un valore vero. Ho controllato le proprietà di ciascuno e corrispondono.

Come confrontare questi due oggetti per verificare che siano identici?

+0

L'ho fatto su Google, ma tutti gli esempi che ho trovato non hanno mai spiegato che bisognava scavalcare il metodo equals. –

+0

@AndroidAddict: Allora perché non hai fatto quella domanda? –

risposta

71

È necessario fornire la propria implementazione di equals() in MyClass.

@Override 
public boolean equals(Object other) { 
    if (!(other instanceof MyClass)) { 
     return false; 
    } 

    MyClass that = (MyClass) other; 

    // Custom equality check here. 
    return this.field1.equals(that.field1) 
     && this.field2.equals(that.field2); 
} 

Si dovrebbe anche ignorare hashCode() se c'è qualche possibilità di oggetti utilizzati in una tabella hash. Un reasonable implementation sarebbe quello di combinare i codici hash dei campi dell'oggetto con qualcosa di simile:

@Override 
public int hashCode() { 
    int hashCode = 1; 

    hashCode = hashCode * 37 + this.field1.hashCode(); 
    hashCode = hashCode * 37 + this.field2.hashCode(); 

    return hashCode; 
} 

Vedere this question per maggiori dettagli su l'implementazione di una funzione di hash.

+1

Perché 37? Un primo? – Aubin

+1

@Aubin In genere, i numeri primi vengono utilizzati nella generazione del codice hash. Se non sbaglio, riduce le probabilità che ci saranno collisioni sugli hash generati. Per quanto riguarda il motivo per cui uso 37, credo che sia solo una scelta popolare, non conosco alcun motivo particolare per l'utilizzo di 37 invece di, per esempio, 13. – afsantos

+0

Grazie - tutto davvero. Tutti mi hanno messo sulla strada giusta, ma posso accettarne solo uno corretto. –

5

Devi eseguire l'override correttamente metodo equals() dalla classe Object

Edit: Credo che la mia prima risposta è stato frainteso, probabilmente perché non ero troppo precisi. Così ho deciso di aggiungere ulteriori spiegazioni.

Perché è necessario eseguire l'override di equals()? Bene, perché questo è nel dominio di uno sviluppatore per decidere cosa significa per due oggetti essere uguali. L'uguaglianza di riferimento non è sufficiente per la maggior parte dei casi.

Ad esempio, immagina di avere una HashMap le cui chiavi sono di tipo Persona. Ogni persona ha nome e indirizzo. Ora, vuoi trovare il bean dettagliato usando la chiave. Il problema è che di solito non sei in grado di creare un'istanza con lo stesso riferimento di quella nella mappa. Quello che fai è creare un'altra istanza di classe Person. Chiaramente, l'operatore == non funzionerà qui e dovrai usare equals().

Ma ora arriviamo a un altro problema. Immaginiamo che la tua collezione sia molto grande e tu voglia eseguire una ricerca. L'implementazione ingenua confronterà il tuo oggetto chiave con ogni istanza in una mappa usando equals(). Ciò, tuttavia, sarebbe molto espansivo. E qui arriva l'hashCode(). Come altri hanno sottolineato, hashcode è un numero unico che non deve essere unico. Il requisito importante è che ogni volta che equals() restituisce true per due oggetti, hashCode() deve restituire lo stesso valore per entrambi. L'implicazione inversa non regge, che è una buona cosa, perché hashcode separa le nostre chiavi in ​​tipi di bucket. Abbiamo un piccolo numero di istanze di classe Person in un singolo bucket. Quando eseguiamo una ricerca, l'algoritmo può saltare immediatamente a un bucket corretto e solo ora esegue equals per ogni istanza. L'implementazione per hashCode() pertanto deve distribuire gli oggetti nel modo più uniforme possibile attraverso i bucket.

C'è un altro punto. Alcune raccolte richiedono una corretta implementazione di un metodo hashCode() nelle classi che vengono utilizzate come chiavi non solo per motivi di prestazioni. Gli esempi sono: HashSet e LinkedHashSet. Se non eseguono l'override di hashCode(), il metodo predefinito Oggetto hashCode() consentirà di aggiungere più oggetti "significativi da uguale" al set di "nessun duplicato consentito".

Alcune delle collezioni che utilizzano hashCode()

  • HashSet
  • LinkedHashSet
  • HashMap

Date un'occhiata a queste due classi di comuni apache che vi permetterà di implementare equals() e hashCode() facilmente

7

È necessario eseguire l'override di equals e hashCode.
equals metterà a confronto gli oggetti per l'uguaglianza in base alle proprietà che ti serve e hashCode è obbligatoria in modo che gli oggetti siano utilizzati in modo corretto e CollectionsMaps

2

1) == valuta le eguaglianza di riferimento in questo caso
2) Non sono troppo sicuro degli uguali, ma perché non semplicemente scavalcare il metodo di confronto e piantarlo all'interno di MyClass?

5

È necessario implementare il metodo equals() nel proprio MyClass.

La ragione per cui lo == non ha funzionato è che si sta verificando che si riferiscono alla stessa istanza. Dato che hai fatto new per ognuno, ognuno è un'istanza diversa.

Il motivo per cui lo equals() non ha funzionato è perché non lo hai ancora implementato. Credo che il comportamento predefinito sia la stessa cosa di ==.

Si noti che è necessario implementare anche hashcode() se si intende implementare equals() poiché si presuppone che molte collezioni java.util si aspettino.

+0

Bella spiegazione. Breve e dritto al punto. – tommyO