2012-02-16 18 views
22

Tengo un problema donde hago una lista ArrayList de objetos, anulo el método equals, y no puedo obtener el método contains para llamar al método equals. He intentado anular iguales y hashcode juntos, pero todavía no funciona. Estoy seguro de que hay una explicación lógica de por qué es esto, pero no puedo resolverlo en este momento en mi propia jaja. Solo quiero ver si la lista contiene la identificación especificada..Contains() método no llamando Ignorar Igual al método

Aquí hay algo de código:

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; 
    } 
} 

SALIDA: falsa falsa falsa

Respuesta

34

Esto es porque su equals() no es simétrica :

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

pero

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

no es cierto. Esto viola la equals() contrato:

El método es igual implementa una relación de equivalencia en las referencias a objetos que no son nulos:

  • [...]

  • Es simétrica : para cualquier valor de referencia no nulo x y y, x.equals(y) debe devolver verdadero si y solo si y.equals(x) devuelve true.

No es reflexiva o bien:

  • Es reflexiva: para cualquier valor de referencia no nulo x, x.equals(x) debe devolver verdadero.
Foo foo = new Foo("ID1"); 
foo.equals(foo) //false! 

@mbockus proporciona la correcta aplicación del equals():

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

pero ahora debe pasar a instancia de Foo :

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

Por último se debe implementar hashCode() para proporcionar resultados consistentes (si dos objetos son igual, ellos deben tener la misma hashCode()):

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

que añadió un sencillo código hash, todavía no funciona ... –

+0

@ReidMac: Estaba equivocado, se trata de 'equals()' no ser simétrico, eche un vistazo a mi edición. 'hashCode()' no tiene nada que ver en este caso, pero igual debe seguir este principio –

+0

Es extraño que necesitemos usar esta 'nueva convención Foo (" ID1 ");' para usar el método personalizado igual. ¿Alguna razón detrás de esto? – Dish

4

debe implementar hashCode

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

pesar de que la contiene obras para ArrayList sin ello. Tus grandes problemas son que tus iguales esperan objetos String, no Foo, y que pidas contener con cadenas. Si la implementación solicitara a cada expulsión en la lista si fueran iguales a la cadena que envía, entonces su código podría funcionar, pero la implementación le pregunta a la cadena si es igual a sus objetos Foo, lo que por supuesto no es.

uso es igual

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

y compruebe contiene

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

Su método es igual necesita ser alterado junto con anulando la función de hashCode(). Actualmente está comprobando si el objeto con el que está comparando es una instancia de String, cuando necesita verificar los objetos Foo.

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

Si utilizas Eclipse, recomiendo tener Eclipse generar el código hash y es igual para usted por ir a la Fuente -> Generar código hash() y equals() ...

+1

+1, copié tu fragmento de código en mi respuesta, espero que no te importe. –

Cuestiones relacionadas