2012-01-08 13 views

Respuesta

249

array1.equals(array2) es lo mismo que array1 == 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 es necesario utilizar Arrays.toString(array).

+48

Tenga en cuenta que 'Arrays.equals()' no funciona como se espera para las matrices multidimensionales, solo compara elementos de la 1ª dimensión para la igualdad de referencia. Apache commons 'ArrayUtils.isEquals' funciona con matrices multidimensionales. –

+3

Estoy aturdido. ¿Hay alguna razón para que array.equals se implemente para la comparación de punteros en lugar de comparar la longitud y cada objeto? – Lake

+2

@Lake is does compara la longitud de la matriz y los objetos contenidos, pero lo que no hace es una comparación profunda. El hecho es que funciona como se esperaba para las matrices. Esto no debería ser un problema en primer lugar. –

71

Es un problema infame: .equals() para matrices está muy roto, pero no lo use, nunca.

Dicho esto, no está "roto" como en "alguien lo ha hecho de una manera realmente incorrecta", simplemente está haciendo lo que está definido y no lo que normalmente se espera. Entonces, para los puristas: está perfectamente bien, y eso también significa que, no lo use nunca.

Ahora el comportamiento esperado para equals es comparar los datos. El comportamiento predeterminado es comparar la identidad, ya que Object no tiene ningún dato (para los puristas: sí lo ha hecho, pero no es el punto); La suposición es que si necesita equals en subclases, lo implementará. En las matrices, no hay implementación para ti, por lo que no debes usarla.

Así que la diferencia es, Arrays.equals(array1, array2) obras como era de esperar (es decir, se compara el contenido), array1.equals(array2) en verano a Object.equals aplicación, que a su vez se compara la identidad, y por lo tanto mejor reemplazado por == (para los puristas: sí que sé de null).

El problema es que incluso Arrays.equals(array1, array2) te morderá mucho si los elementos de la matriz no implementan correctamente equals. Es una afirmación muy ingenua, lo sé, pero hay un caso muy importante que no es 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), por lo que Arrays.equals(array1, array2) no funcionarán como espera en matrices 2D.

Espero que ayude.

+11

No está roto, solo se hereda de Object. –

+1

Realmente no responde la pregunta. Esto es más de un comentario. – AlanFoster

+0

¿Tiene una matriz una implementación personalizada para 'igual()'? Pensé que no fue reemplazado por Object. –

0

equals() de matrices se hereda de Object, por lo que no mira el contenido de las carpetas, solo considera que cada matriz es igual a ella.

Los métodos Arrays.equals()do comparan los contenidos de las matrices. Hay sobrecargas para todos los tipos primitivos, y el de los objetos usa los propios métodos equals() de los objetos.

+2

diga "contenido de matrices", ¿esto quiere decir matrices multidimensionales también? – AlanFoster

+0

@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 de igual a() de sub-arrays –

1

El Arrays.equals(array1, array2): cheque

si ambas matrices contienen el mismo número de elementos, y todos los pares correspondientes de los elementos en las dos matrices son iguales.

El array1.equals(array2):

comparar el objeto a otro objeto y volver cierto sólo si la referencia de los dos objetos son iguales como en los Object.equals()

5

Arrays heredan equals() de Object y por lo tanto comparar sólo devuelve verdadero si comparando una matriz contra sí misma.

Por otro lado, Arrays.equals compara los elementos de las matrices.

Este fragmento de aclaraciones respecto a la diferencia:

Object o1 = new Object(); 
Object o2 = new Object(); 
Object[] a1 = { o1, o2 }; 
Object[] a2 = { o1, o2 }; 
System.out.println(a1.equals(a2)); // prints false 
System.out.println(Arrays.equals(a1, a2)); // prints true 

Ver también Arrays.equals(). Otro método estático también puede ser de interés: Arrays.deepEquals().

15

mirar dentro de la ejecució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 
*/ 
public boolean 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 
*/ 
public static boolean equals(Object[] a, Object[] a2) { 
    if (a==a2) 
     return true; 
    if (a==null || a2==null) 
     return false; 

    int length = a.length; 
    if (a2.length != length) 
     return false; 

    for (int i=0; i<length; i++) { 
     Object o1 = a[i]; 
     Object o2 = a2[i]; 
     if (!(o1==null ? o2==null : o1.equals(o2))) 
      return false; 
    } 

    return true; 
} 
7

suspiro. En los años 70 yo era el "programador de sistemas" (sysadmin) para un sistema IBM 370, y mi empleador era miembro del grupo de usuarios de IBM SHARE. A veces ocurría que alguien enviaba un APAR (informe de error) sobre algún comportamiento inesperado de algún comando CMS, e IBM respondía NOTABUG: el comando hace para lo que fue diseñado (y lo que dice la documentación).

COMPARTIR surgió con un contador a esto: MALO - Roto Como Diseñado. Creo que esto podría aplicarse a esta implementación de iguales para matrices.

No hay nada de malo con la implementación de Object.equals. Object no tiene miembros de datos, por lo que no hay nada para 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 se espera una comparación (a través de iguales) para comparar los datos. Idealmente, la forma en que lo hace Arrays.deepEquals, pero al menos la forma en que lo hace Arrays.equals (comparación superficial de los elementos).

Así que el problema es que la matriz (como un objeto incorporado) no anula Object.equals. String (como una clase con nombre) does anula Object.equals y da el resultado esperado.

Las demás respuestas dadas son correctas: [...]. Equals ([....]) simplemente compara los punteros y no los contenidos. Tal vez algún día alguien corrija esto. O tal vez no: ¿cuántos programas existentes se romperían si [...] iguala realmente comparado los elementos? No muchos, sospecho, pero más que cero.

+2

Me gusta el acrónimo Broken.As.Designed – Chris

0
import java.util.Arrays; 
public class ArrayDemo { 
    public static void main(String[] args) { 
    // initiliazing three object arrays 
    Object[] arr1 = new Object[] { 1, 123 }; 
    Object[] arr2 = new Object[] { 1, 123, 22, 4 }; 
    Object[] arr3 = new Object[] { 1, 123 }; 

    // comparing arr1 and arr2 
    boolean retval=Arrays.equals(arr1, arr2); 
    System.out.println("arr1 and arr2 equal: " + retval); 
    System.out.println("arr1 and arr2 equal: " + arr1.equals(arr2)); 

    // comparing arr1 and arr3 
    boolean retval2=Arrays.equals(arr1, arr3); 
    System.out.println("arr1 and arr3 equal: " + retval2); 
    System.out.println("arr1 and arr2 equal: " + arr1.equals(arr3)); 

    } 
} 

Aquí está la salida:

arr1 and arr2 equal: false 
    arr1 and arr2 equal: false 

    arr1 and arr3 equal: true 
    arr1 and arr3 equal: false 

Al ver este tipo de problema que iría personalmente por Arrays.equals(array1, array2) como por su pregunta para evitar confusiones.