Comparación de matrices en Java

1. Información general

En este tutorial, veremos diferentes formas de comparar matrices en Java . Cubriremos los métodos convencionales y también veremos algunos ejemplos que usan expresiones lambda .

2. Comparación de matrices

Vamos a comparar matrices en Java y, como sabemos, estos son objetos. Por tanto, refresquemos algunos conceptos básicos:

  • Los objetos tienen referencias y valores
  • Dos referencias iguales deben apuntar al mismo valor
  • Dos valores diferentes deben tener referencias diferentes
  • Dos valores iguales no necesariamente tienen las mismas referencias
  • Los valores primitivos solo se comparan por valor
  • Los literales de cadena solo se comparan por valor

2.1. Comparación de referencias de objetos

Si tenemos dos referencias que apuntan a la misma matriz, siempre deberíamos obtener un resultado verdadero en una comparación igual con el operador == .

Veamos un ejemplo:

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" }; String[] planes2 = planes1;

Primero, creamos una matriz de modelos de planos referenciados por planes1 . Luego creamos planos2 , que hace referencia a planos1 . Al hacer esto, estamos creando dos referencias a la misma matriz en la memoria . Por lo tanto, la expresión "planos1 == planos2" devolverá verdadero .

Para matrices, el método equals () es el mismo que el operador == . Entonces, planes1.equals (planes2) devuelve verdadero porque ambas referencias se refieren al mismo objeto. En términos generales, array1.eqauls (array2) devolverá verdadero si y solo si la expresión array1 == array2 ″ devuelve verdadero .

Afirmemos si las dos referencias son iguales:

assertThat(planes1).isSameAs(planes2);

Asegurémonos ahora de que los valores referenciados por planos1 sean en realidad los mismos que los referenciados por planos2 . Por lo tanto, podemos cambiar la matriz referenciada por planes2 y verificar si los cambios tienen algún impacto en la matriz referenciada por planos1 :

planes2[0] = "747";

Para ver finalmente que esto funciona, hagamos nuestras afirmaciones:

assertThat(planes1).isSameAs(planes2); assertThat(planes2[0]).isEqualTo("747"); assertThat(planes1[0]).isEqualTo("747");

Con esta prueba unitaria, pudimos comparar dos matrices por referencia.

Sin embargo, solo hemos probado que una referencia, una vez asignada al valor de otra, hará referencia al mismo valor.

Ahora crearemos dos matrices diferentes con los mismos valores:

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" }; String[] planes2 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" };

Dado que son objetos diferentes, sabemos con certeza que no son lo mismo. Por tanto, podemos compararlos:

assertThat(planes1).isNotSameAs(planes2);

En resumen, en este caso, tenemos dos matrices en la memoria que contienen los mismos valores de cadena en exactamente el mismo orden. Sin embargo, las matrices referenciadas no solo son diferentes en contenido, sino que las referencias en sí mismas también son diferentes.

2.2. Comparación de longitudes de matriz

La longitud de las matrices se puede comparar independientemente de sus tipos de elementos, o si sus valores están completos o no .

Creemos dos matrices:

final String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" }; final Integer[] quantities = new Integer[] { 10, 12, 34, 45, 12, 43, 5, 2 };

Estas son dos matrices diferentes con diferentes tipos de elementos. En este conjunto de datos, estamos registrando, a modo de ejemplo, cuántos aviones de cada modelo se almacenan en el almacén. Ahora ejecutemos pruebas unitarias en ellos:

assertThat(planes1).hasSize(8); assertThat(quantities).hasSize(8);

Con esto, hemos probado que ambas matrices tienen ocho elementos y que la propiedad length devuelve el número correcto de elementos para cada matriz.

2.3. Comparación de matrices con matrices.equals

Hasta ahora, solo comparamos matrices en función de sus identidades de objeto. Por otro lado, para comprobar si dos matrices son iguales en términos de contenido, Java proporciona el método estático Arrays.equals . Este método iterará a través de las matrices, por posición en paralelo, y aplicará el operador ==, para cada par de elementos .

Creemos dos matrices diferentes con los mismos literales String exactamente en el mismo orden:

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" }; String[] planes2 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" };

Y ahora, afirmemos que son iguales:

assertThat(Arrays.equals(planes1, planes2)).isTrue();

Si cambiamos el orden de los valores de la segunda matriz:

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" }; String[] planes2 = new String[] { "B738", "A320", "A321", "A319", "B77W", "B737", "A333", "A332" }; 

Obtendremos un resultado diferente:

assertThat(Arrays.equals(planes1, planes2)).isFalse();

2.4. Comparación de matrices con matrices.deepEquals

Usar el operador == es fácil si usamos tipos simples en Java . Estos pueden ser tipos primitivos o literales de cadena . Una comparación entre matrices de objetos puede ser más complicada. La razón detrás de esto se explica completamente en nuestro artículo Arrays.deepEquals . Veamos un ejemplo.

Primero, comencemos con una clase de avión :

public class Plane { private final String name; private final String model; // getters and setters }

E implementemos los métodos hashCode y equals :

@Override public boolean equals(Object o)  if (this == o) return true; if (o == null  @Override public int hashCode() { return Objects.hash(name, model); }

En segundo lugar, creemos las siguientes matrices de dos elementos:

Plane[][] planes1 = new Plane[][] { new Plane[]{new Plane("Plane 1", "A320")}, new Plane[]{new Plane("Plane 2", "B738") }}; Plane[][] planes2 = new Plane[][] { new Plane[]{new Plane("Plane 1", "A320")}, new Plane[]{new Plane("Plane 2", "B738") }}; 

Veamos ahora si son matrices verdaderas y profundamente iguales:

assertThat(Arrays.deepEquals(planes1, planes2)).isTrue();

Para asegurarnos de que nuestra comparación funcione como se esperaba, cambiemos ahora el orden de nuestra última matriz:

Plane[][] planes1 = new Plane[][] { new Plane[]{new Plane("Plane 1", "A320")}, new Plane[]{new Plane("Plane 2", "B738") }}; Plane[][] planes2 = new Plane[][] { new Plane[]{new Plane("Plane 2", "B738")}, new Plane[]{new Plane("Plane 1", "A320") }};

Finalmente, probemos si de hecho ya no son iguales:

assertThat(Arrays.deepEquals(planes1, planes2)).isFalse();

2.5. Comparación de matrices con diferentes órdenes de elementos

Para comprobar si las matrices son iguales, independientemente del orden de los elementos, necesitamos definir qué hace que una instancia de nuestro Plane sea única . Para nuestro caso, un nombre o modelo diferente es suficiente para determinar que un plano es diferente a otro. Hemos establecido esto al haber implementado ambos métodos hashCode y equals . Esto implica que antes de comparar nuestras matrices, deberíamos ordenarlas. Para eso, necesitamos un Comparador :

Comparator planeComparator = (o1, o2) -> { if (o1.getName().equals(o2.getName())) { return o2.getModel().compareTo(o1.getModel()); } return o2.getName().compareTo(o1.getName()); };

In this Comparator, we're giving priority to the name. If the names are equal, we solve the ambiguity by looking at the model. We compare strings by using the compareTo method of type String.

We want to be able to find if arrays are equal regardless of the sorting order. To do that, let's now sort our arrays:

Arrays.sort(planes1[0], planeComparator); Arrays.sort(planes2[0], planeComparator);

And finally, let's test them:

assertThat(Arrays.deepEquals(planes1, planes2)).isTrue();

Having sorted the arrays in the same order first, we allow the deepEquals method to find if these two arrays are equal.

3. Conclusion

En este tutorial, hemos visto diferentes formas de comparar matrices. En segundo lugar, vimos la diferencia entre comparar referencias y valores. Además, hemos analizado cómo podemos comparar matrices en profundidad . Finalmente, vimos la diferencia entre una comparación normal y una comparación profunda usando equals y deepEquals , respectivamente.

Como siempre, el código fuente completo de los ejemplos está disponible en GitHub.