2010-04-15 18 views
241

Digamos que creo un objeto y lo agrego a mi ArrayList. Si luego creo otro objeto con exactamente la misma entrada de constructor, ¿el método evaluará que los dos objetos sean iguales? Supongamos que el constructor no hace nada gracioso con la entrada, y las variables almacenadas en ambos objetos son idénticas.¿Cómo evalúa los objetos el método contains() de un ArrayList?

ArrayList<Thing> basket = new ArrayList<Thing>(); 
Thing thing = new Thing(100); 
basket.add(thing); 
Thing another = new Thing(100); 
basket.contains(another); // true or false? 

class Thing { 
    public int value; 

    public Thing (int x) { 
     value = x; 
    } 

    equals (Thing x) { 
     if (x.value == value) return true; 
     return false; 
    } 
} 

¿Es así como la class deberían implementarse para tener retorno true?

Respuesta

278

ArrayList implements Interfaz de lista.

Si mira el Javadoc for List en el método contains, verá que utiliza el método equals() para evaluar si dos objetos son iguales.

+55

En caso de que planee anular equals(), asegúrese de anular el método hashcode() también. Si no lo haces, es posible que las cosas no funcionen como se esperaba al usar Colecciones? –

+30

Esta es una respuesta correcta, pero tenga en cuenta que debe cambiar su método equals para aceptar un 'Object' en lugar de' Thing'. Si no lo haces, no se usará tu método igual. :) – mdierker

+0

Acabo de descubrir que el eclipse tiene "Generar hashCode() y es igual a" en el menú de Origen. –

13

ArrayList utiliza el método equals implementado en la clase (su clase Thing de caso) para hacer la comparación de iguales.

+0

THX. ¡Muy apreciado! –

6

Utiliza el método equals en los objetos. De modo que, a menos que Thing overrides sea igual y use las variables almacenadas en los objetos para comparación, no devolverá true en el método .

4

Otros carteles han abordado la pregunta sobre cómo funciona contains().

Un aspecto igualmente importante de su pregunta es cómo implementar correctamente equals(). Y la respuesta a esto depende realmente de lo que constituye la igualdad de objeto para esta clase en particular. En el ejemplo que proporcionó, si tiene dos objetos diferentes que tienen x = 5, ¿son iguales? Realmente depende de lo que estás tratando de hacer.

Si solo está interesado en la igualdad de objetos, la implementación predeterminada de .equals() (la proporcionada por Object) usa solo identidad (es decir, = = otro). Si eso es lo que quieres, entonces no implemente equals() en tu clase (deja que herede de Object). El código que escribió, aunque es correcto si va en busca de identidad, nunca aparecería en una clase real b/c. No proporciona ningún beneficio sobre el uso de la implementación predeterminada de Object.equals().

Si recién está comenzando con estas cosas, le recomiendo encarecidamente el libro Effective Java de Joshua Bloch. Es una gran lectura y cubre este tipo de cosas (además de cómo implementar correctamente iguales() cuando se está tratando de hacer algo más que la identidad comparaciones basadas)

+0

Para mi propósito, estaba tratando de ver si un objeto de igual valor estaba en ArrayList. Supongo que es una especie de truco. Gracias por la recomendación de libro –

10

En general también se debe anular hashCode() cada vez que se reemplaza equals(), incluso si solo por el aumento del rendimiento. HashCode() decide en qué 'cubo' se ordena su objeto al hacer una comparación, por lo que dos objetos que equal() evalúen como verdaderos deben devolver el mismo hashCodevalue(). No recuerdo el comportamiento predeterminado de hashCode() (si devuelve 0, entonces su código debería funcionar pero lentamente, pero si devuelve la dirección, su código fallará). Recuerdo un montón de veces cuando mi código falló porque olvidé anular hashCode().:)

5
class Thing { 
    public int value; 

    public Thing (int x) { 
     value = x; 
    } 

    equals (Thing x) { 
     if (x.value == value) return true; 
     return false; 
    } 
} 

debe escribir:

class Thing { 
    public int value; 

    public Thing (int x) { 
     value = x; 
    } 

    public boolean equals (Object o) { 
    Thing x = (Thing) o; 
     if (x.value == value) return true; 
     return false; 
    } 
} 

Ahora funciona;)

+6

no debe hacer cosa x = (cosa) o; sin antes comprobar si el otro objeto es nulo – steelshark

47

Creo que las implementaciones correctas deben ser

public class Thing 
{ 
    public int value; 

    public Thing (int x) 
    { 
     this.value = x; 
    } 

    @Override 
    public boolean equals(Object object) 
    { 
     boolean sameSame = false; 

     if (object != null && object instanceof Thing) 
     { 
      sameSame = this.value == ((Thing) object).value; 
     } 

     return sameSame; 
    } 
} 
+7

¿dónde está la implementación del método 'hashcode'? – Stephan

+10

Sí, tienes razón @Alex! Siéntase libre de agregarlo;) – ChristopheCVB

+1

declaración 'if' es innecesario. 'instanceof' es suficiente. – Paul

5

Sólo quería tener en cuenta que la siguiente la implementación es incorrecta cuando value no es un tipo primitivo:

public class Thing 
{ 
    public Object value; 

    public Thing (Object x) 
    { 
     this.value = x; 
    } 

    @Override 
    public boolean equals(Object object) 
    { 
     boolean sameSame = false; 

     if (object != null && object instanceof Thing) 
     { 
      sameSame = this.value == ((Thing) object).value; 
     } 

     return sameSame; 
    } 
} 

En ese caso, propongo lo siguiente:

public class Thing { 
    public Object value; 

    public Thing (Object x) { 
     value = x; 
    } 

    @Override 
    public boolean equals(Object object) { 

     if (object != null && object instanceof Thing) { 
      Thing thing = (Thing) object; 
      if (value == null) { 
       return (thing.value == null); 
      } 
      else { 
       return value.equals(thing.value); 
      } 
     } 

     return false; 
    } 
} 
+0

cómo implementar esto mientras se elimina el duplicado? – Sujay

2

acceso directo desde JavaDoc:

booleanocontiene (Object o)

devuelve verdadero si esta lista contiene el elemento especificado. Más formalmente, devuelve verdadero si y sólo si esta lista contiene al menos un elemento de este tipo electrónico que (o == null e == null:? O.equals (e))

Cuestiones relacionadas