objects from example java list equals contains

java - from - List.contains() falla mientras funciona.equals()



override contains java (4)

El hecho de que los Test equals su Test puedan volverse verdaderos cuando le pasa un String no significa que los equals String volverán a ser verdaderos cuando le pase una instancia de Test . De hecho, los equals String solo pueden devolver true cuando la instancia que se le pasa es otra String :

public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { // the passed instance must be a String String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }

ArrayList contains llamadas indexOf que utiliza el método equals de la instancia buscada (la String "a" en su ejemplo), no el tipo de elemento de la List (que es Test en su caso):

public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) // o in your case is a String while // elementData[i] is a Test // so String''s equals returns false return i; } return -1; }

Tengo un objeto ArrayList de objetos de Test , que usan una cadena como verificación de equivalencia. Quiero poder usar List.contains() para verificar si la lista contiene un objeto que usa una cadena determinada.

Simplemente:

Test a = new Test("a"); a.equals("a"); // True List<Test> test = new ArrayList<Test>(); test.add(a); test.contains("a"); // False!

Función de igual y hash:

@Override public boolean equals(Object o) { if (o == null) return false; if (o == this) return true; if (!(o instanceof Test)) { return (o instanceof String) && (name.equals(o)); } Test t = (Test)o; return name.equals(t.GetName()); } @Override public int hashCode() { return name.hashCode(); }

Leí eso para asegurarme de que contains trabajos para una clase personalizada, necesita anular equals . Por lo tanto, es muy extraño para mí que si bien equals devuelve verdadero, contains retornos como falso.

¿Cómo puedo hacer que esto funcione?

Codigo completo


El problema es que List<E>.contains(object o) está documentado para devolver true:

si y solo si esta lista contiene al menos un elemento e tal que (o == null? e == null: o.equals (e)).

(Desde https://docs.oracle.com/javase/8/docs/api/java/util/List.html#contains-java.lang.Object- )

Tenga en cuenta que no realiza la prueba como e.equals(o) que es lo que sería necesario para que su prueba funcione. Su método equals no funciona de manera conmutativa (''simétricamente'' usando los términos de los documentos de Java).

Java documenta que el método equals() para una clase debe seguir estas reglas:

El método equals implementa una relación de equivalencia en referencias de objetos no nulos:

  • Es reflexivo: para cualquier valor de referencia no nulo x , x.equals(x) debe devolver verdadero.
  • Es simétrico: para cualquier valor de referencia no nulo x e y , x.equals(y) debería devolver verdadero si y solo si y.equals(x) devuelve verdadero.
  • Es transitivo: para cualquier valor de referencia no nulo x , y y z , si x.equals(y) devuelve true y y.equals(z) devuelve true, entonces x.equals(z) debe devolver true.
  • Es consistente: para cualquier valor de referencia no nulo y , las múltiples invocaciones de x.equals(y) devuelven consistentemente verdadero o devuelven falso constantemente, siempre que no se modifique la información utilizada en comparaciones iguales en los objetos.
  • Para cualquier valor de referencia que no sea nulo x , x.equals(null) debe devolver falso.

Si tú escribes

test.contains(new Test("a"));

entonces seguramente volverá verdadero. Está buscando un objeto de cadena en la lista de Prueba.


equals() siempre debe ser commutative , es decir, a.equals(b) y b.equals(a) siempre deben devolver el mismo valor. O simétrico , como lo llama el javadoc de equals() :

El método equals implementa una relación de equivalencia en referencias de objetos no nulos:

  • Es reflexivo : para cualquier valor de referencia no nulo x , x.equals(x) debe devolver true .
  • Es simétrico : para cualquier valor de referencia no nulo x e y , x.equals(y) debería devolver true si y solo si y.equals(x) devuelve true .
  • Es transitivo : para cualquier valor de referencia no nulo x , y y z , si x.equals(y) devuelve true y y.equals(z) devuelve true , entonces x.equals(z) debe devolver true .
  • Es consistente : para cualquier valor de referencia no nulo y , las múltiples invocaciones de x.equals(y) devuelven consistentemente true o devuelven false constantemente, siempre que no se modifique la información utilizada en comparaciones equals en los objetos.
  • Para cualquier valor de referencia no nulo x , x.equals(null) debería devolver false .

Desafortunadamente, incluso la Biblioteca de tiempo de ejecución de Java lo equivoca. Date.equals(Timestamp) comparará los valores de milisegundos, ignorando los nanosegundos presentes en la Timestamp , mientras que Timestamp.equals(Date) devuelve false .