Tenga en cuenta que Arrays.equals()no funciona como se esperaba para las matrices multidimensionales, solo compara los elementos de la primera dimensión para la igualdad de referencia. Apache commons ArrayUtils.isEqualsfunciona con matrices multidimensionales.
Adam Parkin
44
Estoy atónito. ¿Hay alguna razón para que array.equals se implemente para comparar punteros en lugar de comparar longitud y cada objeto?
Lago
2
@Lake sí compara la longitud de la matriz y los objetos contenidos, pero lo que no hace es una comparación profunda. El hecho de que igual funciona como se esperaba para las matrices está roto, esto no debería ser un problema en primer lugar.
@JeewanthaSamaraweera esa es la definición de ese método, sin embargo .equals, porque no compara el contenido, es por eso que necesita ese método.
Peter Lawrey
86
Es un problema infame: .equals()para las matrices está muy roto, simplemente no lo use nunca.
Dicho esto, no está "roto" como en "alguien lo ha hecho de una manera realmente incorrecta", solo está haciendo lo que se define y no lo que generalmente se espera. Entonces, para los puristas: está perfectamente bien, y eso también significa que no lo uses nunca.
Ahora el comportamiento esperado para equalses comparar datos. El comportamiento predeterminado es comparar la identidad, ya Objectque no tiene ningún dato (para los puristas: sí, pero no es el punto); la suposición es que, si necesita equalsen subclases, lo implementará. En las matrices, no hay implementación para usted, por lo que no debe usarla.
Entonces, la diferencia es que Arrays.equals(array1, array2)funciona como era de esperar (es decir, compara el contenido), array1.equals(array2)recurre a la Object.equalsimplementación, que a su vez compara la identidad y, por lo tanto, se reemplaza mejor por ==(para los puristas: sí, lo sé null).
El problema es que incluso Arrays.equals(array1, array2)te morderá duro si los elementos de la matriz no se implementanequals correctamente. Es una declaración muy ingenua, lo sé, pero hay un caso muy importante menos que obvio: considere una matriz 2D.
La matriz 2D en Java es una matriz de matrices, y las matrices equalsestán rotas (o inútiles si lo prefiere), por Arrays.equals(array1, array2)lo que no funcionarán como espera en las matrices 2D.
¿Tiene una matriz una implementación personalizada equals()? Pensé que no fue anulado por Object.
Martijn Courteaux
@MichaelBorgwardt es una biblioteca de sistema, con un método que no hace lo que se dice en el javadoc. Suena bastante roto para mí. Dicho esto, admito que es una afirmación muy discutible, pero creo que "está roto" se recuerda mejor y, por lo tanto, es mucho más conveniente pensarlo de esta manera.
alf
@MartijnCourteaux ese es exactamente el problema :)
alf
3
Para las matrices de matrices, necesita Arrays.deepEquals--- es lo que someArray.equalsdebería haber hecho todo el tiempo. (Relacionado:. Objects.deepEquals)
Kevin J. Chase
16
Mire dentro de la implementación de los dos métodos para comprenderlos profundamente:
array1.equals(array2);
/**
* Indicates whether some other object is "equal to" this one.
* <p>
* The {@code equals} method implements an equivalence relation
* on non-null object references:
* <ul>
* <li>It is <i>reflexive</i>: for any non-null reference value
* {@code x}, {@code x.equals(x)} should return
* {@code true}.
* <li>It is <i>symmetric</i>: for any non-null reference values
* {@code x} and {@code y}, {@code x.equals(y)}
* should return {@code true} if and only if
* {@code y.equals(x)} returns {@code true}.
* <li>It is <i>transitive</i>: for any non-null reference values
* {@code x}, {@code y}, and {@code z}, if
* {@code x.equals(y)} returns {@code true} and
* {@code y.equals(z)} returns {@code true}, then
* {@code x.equals(z)} should return {@code true}.
* <li>It is <i>consistent</i>: for any non-null reference values
* {@code x} and {@code y}, multiple invocations of
* {@code x.equals(y)} consistently return {@code true}
* or consistently return {@code false}, provided no
* information used in {@code equals} comparisons on the
* objects is modified.
* <li>For any non-null reference value {@code x},
* {@code x.equals(null)} should return {@code false}.
* </ul>
* <p>
* The {@code equals} method for class {@code Object} implements
* the most discriminating possible equivalence relation on objects;
* that is, for any non-null reference values {@code x} and
* {@code y}, this method returns {@code true} if and only
* if {@code x} and {@code y} refer to the same object
* ({@code x == y} has the value {@code true}).
* <p>
* Note that it is generally necessary to override the {@code hashCode}
* method whenever this method is overridden, so as to maintain the
* general contract for the {@code hashCode} method, which states
* that equal objects must have equal hash codes.
*
* @param obj the reference object with which to compare.
* @return {@code true} if this object is the same as the obj
* argument; {@code false} otherwise.
* @see #hashCode()
* @see java.util.HashMap
*/publicboolean equals(Object obj){return(this== obj);}
mientras:
Arrays.equals(array1, array2);
/**
* Returns <tt>true</tt> if the two specified arrays of Objects are
* <i>equal</i> to one another. The two arrays are considered equal if
* both arrays contain the same number of elements, and all corresponding
* pairs of elements in the two arrays are equal. Two objects <tt>e1</tt>
* and <tt>e2</tt> are considered <i>equal</i> if <tt>(e1==null ? e2==null
* : e1.equals(e2))</tt>. In other words, the two arrays are equal if
* they contain the same elements in the same order. Also, two array
* references are considered equal if both are <tt>null</tt>.<p>
*
* @param a one array to be tested for equality
* @param a2 the other array to be tested for equality
* @return <tt>true</tt> if the two arrays are equal
*/publicstaticboolean equals(Object[] a,Object[] a2){if(a==a2)returntrue;if(a==null|| a2==null)returnfalse;int length = a.length;if(a2.length != length)returnfalse;for(int i=0; i<length; i++){Object o1 = a[i];Object o2 = a2[i];if(!(o1==null? o2==null: o1.equals(o2)))returnfalse;}returntrue;}
Suspiro. En los años 70, yo era el "programador del sistema" (sysadmin) para un sistema IBM 370, y mi empleador era miembro del grupo de usuarios de IBM SHARE. A veces sucede que alguien envió un APAR (informe de error) sobre un comportamiento inesperado de algún comando CMS, e IBM respondería NOTABUG: el comando hace lo que fue diseñado para hacer (y lo que dice la documentación).
COMPARTIR apareció con un contador para esto: MALO - Roto según lo diseñado. Creo que esto podría aplicarse a esta implementación de iguales para matrices.
No hay nada malo con la implementación de Object.equals. El objeto no tiene miembros de datos, por lo que no hay nada que comparar. Dos "Objetos" son iguales si y solo si son, de hecho, el mismo Objeto (internamente, la misma dirección y longitud).
Pero esa lógica no se aplica a las matrices. Las matrices tienen datos, y usted espera que la comparación (a través de iguales) compare los datos. Idealmente, como lo hace Arrays.deepEquals, pero al menos como lo hace Arrays.equals (comparación superficial de los elementos).
Entonces, el problema es que la matriz (como un objeto incorporado) no anula Object.equals. String (como una clase llamada) hace anulación Object.equals y dar el resultado que espera.
Otras respuestas dadas son correctas: [...]. Igual ([....]) simplemente compara los punteros y no los contenidos. Quizás algún día alguien corrija esto. O tal vez no: ¿cuántos programas existentes se romperían si [...]. Igual realmente comparara los elementos? No muchos, sospecho, pero más de cero.
El equals()de las matrices se hereda de Object, por lo que no mira el contenido de las matrices, solo considera que cada matriz es igual a sí misma.
Los Arrays.equals()métodos no comparar el contenido de las matrices. Hay sobrecargas para todos los tipos primitivos, y la de los objetos usa los propios equals()métodos de los objetos .
dices "contenidos de matrices", ¿significa esto también matrices multidimensionales?
AlanFoster
@AlanFoster: no. Las matrices multidimensionales son matrices de matrices, lo que significa que se invocará el método Arrays.equals (Object [], Object []), que llama a los métodos 'equals () de las sub-matrices
Michael Borgwardt
0
import java.util.Arrays;publicclassArrayDemo{publicstaticvoid main(String[] args){// initializing three object arraysObject[] array1 =newObject[]{1,123};Object[] array2 =newObject[]{1,123,22,4};Object[] array3 =newObject[]{1,123};// comparing array1 and array2boolean retval=Arrays.equals(array1, array2);System.out.println("array1 and array2 equal: "+ retval);System.out.println("array1 and array2 equal: "+ array1.equals(array2));// comparing array1 and array3boolean retval2=Arrays.equals(array1, array3);System.out.println("array1 and array3 equal: "+ retval2);System.out.println("array1 and array3 equal: "+ array1.equals(array3));}}
Aquí está la salida:
array1 and array2 equal:false
array1 and array2 equal:false
array1 and array3 equal:true
array1 and array3 equal:false
Al ver este tipo de problema, personalmente iría Arrays.equals(array1, array2)según su pregunta para evitar confusiones.
Parece correcto, pero en las matrices, el orden de los elementos también es importante. Por ejemplo, si hay otra matriz Object [] array4 = new Object [] {123, 1}; con Arrays.equals (array3, array4), devolverá falso.
Respuestas:
array1.equals(array2)
es igual quearray1 == array2
, es decir, es la misma matriz. Como @alf señala, no es lo que la mayoría de la gente espera.Arrays.equals(array1, array2)
compara el contenido de las matrices.Del mismo modo,
array.toString()
puede no ser muy útil y debe usarArrays.toString(array)
.fuente
Arrays.equals()
no funciona como se esperaba para las matrices multidimensionales, solo compara los elementos de la primera dimensión para la igualdad de referencia. Apache commonsArrayUtils.isEquals
funciona con matrices multidimensionales.Arrays.deepEquals(Object[], Object[])
..equals
, porque no compara el contenido, es por eso que necesita ese método.Es un problema infame:
.equals()
para las matrices está muy roto, simplemente no lo use nunca.Dicho esto, no está "roto" como en "alguien lo ha hecho de una manera realmente incorrecta", solo está haciendo lo que se define y no lo que generalmente se espera. Entonces, para los puristas: está perfectamente bien, y eso también significa que no lo uses nunca.
Ahora el comportamiento esperado para
equals
es comparar datos. El comportamiento predeterminado es comparar la identidad, yaObject
que no tiene ningún dato (para los puristas: sí, pero no es el punto); la suposición es que, si necesitaequals
en subclases, lo implementará. En las matrices, no hay implementación para usted, por lo que no debe usarla.Entonces, la diferencia es que
Arrays.equals(array1, array2)
funciona como era de esperar (es decir, compara el contenido),array1.equals(array2)
recurre a laObject.equals
implementación, que a su vez compara la identidad y, por lo tanto, se reemplaza mejor por==
(para los puristas: sí, lo sénull
).El problema es que incluso
Arrays.equals(array1, array2)
te morderá duro si los elementos de la matriz no se implementanequals
correctamente. Es una declaración muy ingenua, lo sé, pero hay un caso muy importante menos que obvio: considere una matriz 2D.La matriz 2D en Java es una matriz de matrices, y las matrices
equals
están rotas (o inútiles si lo prefiere), porArrays.equals(array1, array2)
lo que no funcionarán como espera en las matrices 2D.Espero que ayude.
fuente
equals()
? Pensé que no fue anulado por Object.Arrays.deepEquals
--- es lo quesomeArray.equals
debería haber hecho todo el tiempo. (Relacionado:.Objects.deepEquals
)Mire dentro de la implementación de los dos métodos para comprenderlos profundamente:
mientras:
fuente
Suspiro. En los años 70, yo era el "programador del sistema" (sysadmin) para un sistema IBM 370, y mi empleador era miembro del grupo de usuarios de IBM SHARE. A veces sucede que alguien envió un APAR (informe de error) sobre un comportamiento inesperado de algún comando CMS, e IBM respondería NOTABUG: el comando hace lo que fue diseñado para hacer (y lo que dice la documentación).
COMPARTIR apareció con un contador para esto: MALO - Roto según lo diseñado. Creo que esto podría aplicarse a esta implementación de iguales para matrices.
No hay nada malo con la implementación de Object.equals. El objeto no tiene miembros de datos, por lo que no hay nada que comparar. Dos "Objetos" son iguales si y solo si son, de hecho, el mismo Objeto (internamente, la misma dirección y longitud).
Pero esa lógica no se aplica a las matrices. Las matrices tienen datos, y usted espera que la comparación (a través de iguales) compare los datos. Idealmente, como lo hace Arrays.deepEquals, pero al menos como lo hace Arrays.equals (comparación superficial de los elementos).
Entonces, el problema es que la matriz (como un objeto incorporado) no anula Object.equals. String (como una clase llamada) hace anulación Object.equals y dar el resultado que espera.
Otras respuestas dadas son correctas: [...]. Igual ([....]) simplemente compara los punteros y no los contenidos. Quizás algún día alguien corrija esto. O tal vez no: ¿cuántos programas existentes se romperían si [...]. Igual realmente comparara los elementos? No muchos, sospecho, pero más de cero.
fuente
Las matrices heredar
equals()
a partirObject
y por lo tanto se comparan sólo devuelve cierto si la comparación de una serie contra sí mismo.Por otro lado,
Arrays.equals
compara los elementos de las matrices.Este fragmento aclara la diferencia:
Ver también
Arrays.equals()
. Otro método estático también puede ser de interés:Arrays.deepEquals()
.fuente
El
Arrays.equals(array1, array2)
:compruebe si ambas matrices contienen el mismo número de elementos, y todos los pares de elementos correspondientes en las dos matrices son iguales.
El
array1.equals(array2)
:compare el objeto con otro objeto y devuelva verdadero solo si la referencia de los dos objetos es igual que en el
Object.equals()
fuente
El
equals()
de las matrices se hereda deObject
, por lo que no mira el contenido de las matrices, solo considera que cada matriz es igual a sí misma.Los
Arrays.equals()
métodos no comparar el contenido de las matrices. Hay sobrecargas para todos los tipos primitivos, y la de los objetos usa los propiosequals()
métodos de los objetos .fuente
Aquí está la salida:
Al ver este tipo de problema, personalmente iría
Arrays.equals(array1, array2)
según su pregunta para evitar confusiones.fuente