Comparaison de tableaux en Java

1. Vue d'ensemble

Dans ce didacticiel, nous allons examiner différentes façons de comparer des tableaux en Java . Nous aborderons les méthodes conventionnelles, et nous verrons également quelques exemples utilisant des expressions lambda .

2. Comparaison de tableaux

Nous allons comparer des tableaux en Java, et comme nous le savons, ce sont des objets. Par conséquent, rafraîchissons quelques concepts de base:

  • Les objets ont des références et des valeurs
  • Deux références égales doivent pointer vers la même valeur
  • Deux valeurs différentes doivent avoir des références différentes
  • Deux valeurs égales n'ont pas nécessairement les mêmes références
  • Les valeurs primitives ne sont comparées que par valeur
  • Les littéraux de chaîne ne sont comparés que par valeur

2.1. Comparaison des références d'objets

Si nous avons deux références pointant vers le même tableau, nous devrions toujours obtenir un résultat vrai dans une comparaison égale avec l' opérateur == .

Regardons un exemple:

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

Tout d'abord, nous avons créé un tableau de modèles de plans référencés par plans1 . Nous créons ensuite planes2 , qui fait référence aux plans1 . En faisant cela, nous créons deux références au même tableau en mémoire . Par conséquent, l' expression «planes1 == planes2» retournera true .

Pour les tableaux, la méthode equals () est la même que l'opérateur == . Ainsi, planes1.equals (planes2) renvoie true car les deux références font référence au même objet. De manière générale, array1.eqauls (array2) retournera true si et seulement si l'expression « array1 == array2» renvoie true .

Affirmons si les deux références sont les mêmes:

assertThat(planes1).isSameAs(planes2);

Assurons-nous maintenant que les valeurs référencées par planes1 sont bien les mêmes que celles référencées par planes2 . Par conséquent, nous pouvons changer le tableau référencé par planes2, et vérifier si les modifications ont un impact sur le tableau référencé par planes1 :

planes2[0] = "747";

Pour enfin voir cela fonctionner, faisons nos affirmations:

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

Avec ce test unitaire, nous avons pu comparer deux tableaux par référence.

Cependant, nous avons seulement prouvé qu'une référence, une fois affectée à la valeur d'une autre, référencera la même valeur.

Nous allons maintenant créer deux tableaux différents avec les mêmes valeurs:

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

Puisqu'il s'agit d'objets différents, nous savons avec certitude qu'ils ne sont pas les mêmes. On peut donc les comparer:

assertThat(planes1).isNotSameAs(planes2);

Pour résumer, dans ce cas, nous avons deux tableaux en mémoire qui contiennent les mêmes valeurs String dans exactement le même ordre. Cependant, non seulement les tableaux référencés ont un contenu différent, mais les références elles-mêmes sont également différentes.

2.2. Comparaison des longueurs de matrice

La longueur des tableaux peut être comparée quels que soient leurs types d'éléments, ou que leurs valeurs soient renseignées ou non .

Créons deux tableaux:

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 };

Ce sont deux tableaux différents avec des types d'éléments différents. Dans cet ensemble de données, nous enregistrons, à titre d'exemple, le nombre d'avions de chaque modèle stockés dans l'entrepôt. Lançons maintenant des tests unitaires sur eux:

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

Avec cela, nous avons prouvé que les deux tableaux ont huit éléments et que la propriété length renvoie le nombre correct d'éléments pour chaque tableau.

2.3. Comparaison de tableaux avec Arrays.equals

Jusqu'à présent, nous n'avons comparé que les tableaux en fonction de leurs identités d'objet. D'autre part, pour vérifier si deux tableaux sont égaux en termes de contenu, Java fournit la méthode statique Arrays.equals . Cette méthode parcourt les tableaux, par position en parallèle, et applique l'opérateur ==, pour chaque paire d'éléments .

Créons deux tableaux différents avec les mêmes littéraux String dans exactement le même ordre:

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

Et maintenant, affirmons qu'ils sont égaux:

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

Si nous changeons l'ordre des valeurs du deuxième tableau:

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

Nous obtiendrons un résultat différent:

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

2.4. Comparaison de tableaux avec Arrays.deepEquals

L'utilisation de l' opérateur == est facile si nous utilisons des types simples en Java . Il peut s'agir de types primitifs ou de littéraux String . Une comparaison entre des tableaux d' objets peut être plus compliquée. La raison en est expliquée en détail dans notre article Arrays.deepEquals . Voyons un exemple.

Commençons par une classe Plane :

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

Et, implémentons les méthodes hashCode et equals :

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

Deuxièmement, créons les tableaux à deux éléments suivants:

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") }}; 

Voyons maintenant s'ils sont vrais, des tableaux profondément égaux:

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

Pour nous assurer que notre comparaison fonctionne comme prévu, modifions maintenant l'ordre de notre dernier tableau:

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") }};

Enfin, testons s'ils ne sont effectivement plus égaux:

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

2.5. Comparaison de tableaux avec différents ordres d'éléments

Pour vérifier si les tableaux sont égaux, quel que soit l'ordre des éléments, nous devons définir ce qui rend une instance de notre plan unique . Dans notre cas, un nom ou un modèle différent suffit pour déterminer qu'un plan est différent d'un autre. Nous avons établi cela en ayant déjà implémenté les méthodes hashCode et equals . Cela implique qu'avant de pouvoir comparer nos tableaux, nous devons les trier. Pour cela, nous avons besoin d'un comparateur :

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

Dans ce didacticiel, nous avons vu différentes façons de comparer des tableaux. Deuxièmement, nous avons vu la différence entre comparer des références et des valeurs. En outre, nous avons examiné comment nous pouvons comparer les tableaux en profondeur . Enfin, nous avons vu la différence entre une comparaison normale et une comparaison approfondie en utilisant respectivement equals et deepEquals .

Comme toujours, le code source complet des exemples est disponible à l'adresse over sur GitHub.