2009-06-12 15 views
8

Tengo un ArrayList en Java que se compone de un tipo que contiene dos cadenas y un entero. Puedo probar con éxito si un elemento de este ArrayList es igual a otro, pero creo que falla el método contains. Creo que esto se debe al hecho de que mi tipo no es primitivo.¿La mejor manera de usar contiene en una ArrayList en Java?

Ahora veo dos alternativas a esto y me pregunto cuál es la mejor opción:

  1. Para poner en práctica mi propio método contains por iteración a través del ArrayList y probando la igualdad de cada elemento contra el que estoy buscando y luego rompiendo el ciclo.

  2. O para usar un HashMap de mi tipo como clave con un entero como valor en lugar de ArrayList. Aquí puedo usar el método containsKey para verificar si un elemento ya existe en HashMap.

La única advertencia con respecto al n. ° 2 es que el valor es en gran medida redundante en mi caso.

+1

Mire el código fuente de ArrayList y verá que la implementación ya es bastante simple. – iny

Respuesta

24

Lo más probable es que simplemente haya olvidado anular equals() y hashCode() en su tipo. equals() es lo que busca.

Desde el Javadoc:

devoluciones true si esta lista contiene el elemento especificado. Más formalmente, devuelve true si y solo si esta lista contiene al menos un elemento e tal que (o==null ? e==null : o.equals(e)).

Dado que la implementación predeterminada de equals prueba la igualdad de referencia, no es adecuada para tipos de datos personalizados como este.

(. Y si no anular equals y hashCode, usando sus tipos como claves en un HashMap sería igualmente inútil)


Editar: Tenga en cuenta que para anular, debe proporcionar la exacta firma.

class MyDataType { 
    public boolean equals(MyDataType other) { // WRONG! 
     ... 
    } 
    public boolean equals(Object other) { // Right! 
     ... 
    } 
} 

Este es un argumento muy fuerte para el uso de la anotación @Override; el primer ejemplo habría fallado en el momento de la compilación si se hubiera anotado con @Override.

+0

En mi clase que he especificado un método es igual a:.. boolean equals privadas (HTE) HierarchicalTreemapElement { if (((this.getChild) iguales (hte.getChild()) && (this.getParent() es igual a (hte.getParent()) && (this.getQuantity() == (hte.getQuantity()))))) { return true; } else { return false; } } Pero contiene aún falla si se utiliza una lista de arrays. ¿Qué necesito hacer para hashCode? –

+3

Has reemplazado equals() incorrectamente, como dice Jon Skeet. Coloque una anotación @Override delante de la firma del método para asegurarse (si no es correcto, generará un error de compilación). –

+1

Para hashCode, si ya lo ha redefinido, probablemente sea suficiente. Si no lo has hecho, definitivamente deberías hacerlo; reemplazando equals() debería * siempre * implicar anular hashCode(). –

3

¿Has anulado el método equals? Esto es necesario para hacer que el contenido funcione correctamente.

0

¿podría usar la clase Entero? entonces usted puede hacer la comparación de objetos

14

Supongo que usted solo ha escrito un método "fuertemente tipado" en lugar de anular iguales (Objeto).En otras palabras, si usted tiene:

public boolean equals(Foo f) 

necesita

public boolean equals(Object o) 

así para anular Object.equals.

que encajaría con "es igual a las obras, pero no contiene ya las pruebas probablemente llaman los iguales de tipo fuerte, pero ArrayList no.

+0

Para ampliar el comentario "pasa tus pruebas pero falla", ten en cuenta que si pruebas MyClass # iguales, deberías hacerlo usando llamadas contra Object # equal, pasando un Object. (Hace una nota para arreglar sus pruebas unitarias, ya que piensa que no está haciendo bien esto). –

+0

Hmm ... No estoy seguro de que mi respuesta realmente agregue algo a la respuesta de mmyers. Tetsujin no Oni: ¿quieres copiar tu comentario a esa respuesta, y luego puedo eliminar este? –

2

Recuerde que si no se sobreescribe los método equals() , entonces dos objetos de su tipo son solo iguales si son misma instancia de ese objeto. La clase ArrayList usa este método para verificar que contiene el objeto dado. Además, debe coincidir exactamente con la firma, lo que significa que debe tomar un Objeto como parámetro y no un Foo.

Además, el contrato de Objeto estipula que debe anular hashCode() siempre que invalide e es igual a(). Si no hace esto, un HashMap o HashSet no identificará sus dos objetos como iguales, incluso si ArrayList lo hace (HashMap comprueba si hay hash idénticos y luego llama a igual() sobre ellos para verificar la igualdad real). Por lo tanto, si ArrayList dice que dos elementos no son iguales, entonces tampoco hay forma de que HashMap lo haga. Esto significa que su segunda solución no funciona.

Mi recomendación es comprobar que realmente anula equals() y hashCode() correctamente y que sus firmas coincidan con las de la clase Object.

Cuestiones relacionadas