2012-02-16 14 views
22

Ho un problema in cui creo un oggetto ArrayList di Foo, sovrascrivo il metodo equals e non riesco a ottenere il metodo contains per chiamare il metodo equals. Ho provato a eseguire l'override di equals e hashcode, ma non funziona ancora. Sono sicuro che c'è una spiegazione logica del perché questo è, ma non riesco a capirlo al momento sul mio lol. Voglio solo un modo per vedere se la lista contiene l'id specificato..Contains() metodo che non chiama Override uguale al metodo

Ecco po 'di codice:

import java.util.ArrayList; 
import java.util.List; 

public class Foo { 

    private String id; 


    public static void main(String... args){ 
     Foo a = new Foo("ID1"); 
     Foo b = new Foo("ID2"); 
     Foo c = new Foo("ID3"); 
     List<Foo> fooList = new ArrayList<Foo>(); 
     fooList.add(a); 
     fooList.add(b); 
     fooList.add(c); 
     System.out.println(fooList.contains("ID1")); 
     System.out.println(fooList.contains("ID2")); 
     System.out.println(fooList.contains("ID5")); 
    } 

    public Foo(String id){ 
     this.id = id; 
    } 

    @Override 
    public boolean equals(Object o){ 
     if(o instanceof String){ 
      String toCompare = (String) o; 
      return id.equals(toCompare); 
     } 
     return false; 
    } 



    @Override 
    public int hashCode(){ 
     return 1; 
    } 
} 

USCITA: falso falso falso

risposta

34

Questo perché il equals() non è simmetrica :

new Foo("ID1").equals("ID1"); 

ma

"ID1".equals(new Foo("ID1")); 

non è vero. Questo viola il contratto di equals():

Il equivale metodo implementa una relazione di equivalenza su riferimenti a oggetti non nulli:

  • [...]

  • È simmetrica: per eventuali valori di riferimento non nulli x e , x.equals(y) devono restituire true se e solo se y.equals(x) restituisce true.

Non è riflessiva uno:

  • È riflessiva: per ogni valore di riferimento non nullo x, x.equals(x) dovrebbe restituire true.
Foo foo = new Foo("ID1"); 
foo.equals(foo) //false! 

@mbockus fornisce corretta attuazione equals():

public boolean equals(Object o){ 
    if(o instanceof Foo){ 
    Foo toCompare = (Foo) o; 
    return this.id.equals(toCompare.id); 
    } 
    return false; 
} 

ma ora si deve passare un'istanza di Foo a :

System.out.println(fooList.contains(new Foo("ID1"))); 
System.out.println(fooList.contains(new Foo("ID2"))); 
System.out.println(fooList.contains(new Foo("ID5"))); 

Infine si dovrebbe implementare hashCode() per fornire risultati coerenti (se due oggetti sono uguali, devono avere uguali hashCode()):

@Override 
public int hashCode() { 
    return id.hashCode(); 
} 
+0

ho aggiunto un semplice codice hash, ancora non funziona ... –

+0

@ReidMac: mi sbagliavo, si tratta di 'equals()' non essendo simmetrico, dai un'occhiata alla mia modifica. 'hashCode()' non ha nulla da fare in questo caso, ma dovresti comunque seguire questo principio –

+0

Strano che abbiamo bisogno di usare questa 'nuova Foo (" ID1 ");' convenzione per usare il metodo degli uguali personalizzati. Qualche ragione dietro a questo? – Dish

4

è necessario implementare hashCode

@Override 
public int hashCode() { 
    return id.hashCode(); 
} 

anche se la contiene lavori per ArrayList Senza esso. I tuoi grossi problemi sono che i tuoi pari si aspettano che String, non oggetti di Foo e che tu chiedi contiene con le stringhe. Se l'implementazione chiedesse ad ogni espulsione nell'elenco se fossero uguali alla stringa che invii, allora il tuo codice potrebbe funzionare, ma l'implementazione chiede alla stringa se è uguale ai tuoi obietti di Foo che ovviamente non è.

Usa equivale

@Override 
public boolean equals(Object o){ 
    if(o instanceof Foo){ 
     String toCompare = ((Foo) o).id; 
     return id.equals(toCompare); 
    } 
    return false; 
} 

e quindi controllare contiene

System.out.println(fooList.contains(new Foo("ID1"))); 
9

tuo metodo equals deve essere modificata con l'override la funzione hashCode(). Attualmente stai controllando se l'oggetto a cui stai confrontando è un'istanza di String, quando devi controllare gli oggetti Foo.

public boolean equals(Object o){ 
    if(o instanceof Foo){ 
     Foo toCompare = (Foo) o; 
     return this.id.equals(toCompare.id); 
    } 
    return false; 
} 

Se stai usando Eclipse, io consiglierei visto Eclipse generare il hashCode e uguale per voi andando a Fonte -> Genera codice hash() e equals() ...

+1

+1, ho copiato il tuo snippet di codice nella mia risposta, spero non ti dispiaccia. –

Problemi correlati