244 votes

Égal contre Arrays.equals en Java

Lors de la comparaison des tableaux en Java, existe-t-il des différences entre les 2 déclarations suivantes ?

Object[] tableau1, tableau2;
tableau1.equals(tableau2);
Arrays.equals(tableau1, tableau2);

Et si oui, quelles sont-elles ?

0 votes

Regardez également java.util.Arrays.deepEquals(Object[] a1, Object[] a2)

0 votes

J'ai signalé un commentaire pour suppression car il est conversationnel / une réponse, et ne concerne pas l'amélioration de la question actuelle. Si cela est supprimé, veuillez également supprimer mon commentaire :)

345voto

Peter Lawrey Points 229686

array1.equals(array2) est la même chose que array1 == array2, c'est-à-dire qu'il s'agit du même tableau. Comme le souligne @alf, ce n'est pas ce à quoi la plupart des gens s'attendent.

Arrays.equals(array1, array2) compare le contenu des tableaux.


De même, array.toString() peut ne pas être très utile et vous devez utiliser Arrays.toString(array).

66 votes

Notez que Arrays.equals() ne fonctionne pas comme prévu pour les tableaux multidimensionnels, il ne compare que les éléments de la 1ère dimension pour l'égalité de référence. Apache commons ArrayUtils.isEquals fonctionne avec des tableaux multidimensionnels.

7 votes

Je suis stupéfait. Y a-t-il une raison pour que array.equals soit implémenté pour la comparaison de pointeurs plutôt que de comparer la longueur et chaque objet?

2 votes

@Lake compare la longueur du tableau et les objets contenus, mais ce qu'il ne fait pas, c'est une comparaison approfondie. Le fait qu'équals fonctionne comme prévu pour les tableaux est cassé, cela ne devrait pas être un problème en premier lieu.

95voto

alf Points 5130

C'est un problème tristement célèbre : .equals() pour les tableaux est gravement défectueux, ne l'utilisez jamais.

Ceci dit, ce n'est pas "défectueux" au sens de "quelqu'un l'a fait de manière vraiment incorrecte" — il fait simplement ce qui est défini et pas ce qui est généralement attendu. Donc pour les puristes : c'est parfaitement acceptable, et cela signifie aussi, ne l'utilisez jamais.

Maintenant, le comportement attendu pour equals est de comparer les données. Le comportement par défaut est de comparer l'identité, puisque Object n'a pas de données (pour les puristes : oui, il en a, mais ce n'est pas le point) ; on suppose donc que si vous avez besoin de equals dans les sous-classes, vous l'implémenterez. Dans les tableaux, il n'y a pas d'implémentation pour vous, donc vous n'êtes pas censé l'utiliser.

Donc la différence est que Arrays.equals(array1, array2) fonctionne comme vous vous y attendez (c'est-à-dire, compare le contenu), array1.equals(array2) renvoie à l'implémentation de Object.equals, qui compare l'identité, et est donc mieux remplacé par == (pour les puristes : oui je sais à propos de null).

Le problème est que même Arrays.equals(array1, array2) vous causera des problèmes si les éléments du tableau n'implémentent pas correctement equals. C'est une affirmation très naïve, je le sais, mais il y a un cas très important moins évident : considérez un tableau en 2D.

Un tableau en 2D en Java est un tableau de tableaux, et equals des tableaux est défectueux (ou inutile si vous préférez), donc Arrays.equals(array1, array2) ne fonctionnera pas comme vous l'attendez sur les tableaux en 2D.

16 votes

Ce n'est pas cassé, c'est juste hérité de l'objet.

0 votes

L'array a-t-il une implementation personnalisée pour equals()? Je pensais qu'il n'était pas redéfini à partir de Object.

0 votes

@MichaelBorgwardt c'est une bibliothèque système, avec une méthode qui ne fait pas ce qui est dit dans le javadoc. Ça semble assez cassé pour moi. Cela dit, j'admets que c'est une déclaration très discutable, mais je crois que "c'est cassé" est mieux mémorisé, et donc c'est beaucoup plus pratique d'y penser de cette façon.

20voto

Eng.Fouad Points 44085

Regardez à l'intérieur de l'implémentation des deux méthodes pour les comprendre en profondeur :

array1.equals(array2);

/**
 * Indique si un autre objet est "égal à" celui-ci.
 * 
 * La méthode {@code equals} implémente une relation d'équivalence
 * sur les références d'objet non nulles :
 * 
 * Elle est réflexive : pour toute valeur de référence non nulle
 *     {@code x}, {@code x.equals(x)} devrait retourner
 *     {@code true}.
 * Elle est symétrique : pour toute valeur de référence non nulle
 *     {@code x} et {@code y}, {@code x.equals(y)}
 *     devrait retourner {@code true} si et seulement si
 *     {@code y.equals(x)} retourne {@code true}.
 * Elle est transitive : pour toute valeur de référence non nulle
 *     {@code x}, {@code y}, et {@code z}, si
 *     {@code x.equals(y)} retourne {@code true} et
 *     {@code y.equals(z)} retourne {@code true}, alors
 *     {@code x.equals(z)} devrait retourner {@code true}.
 * Elle est cohérente : pour toute valeur de référence non nulle
 *     {@code x} et {@code y}, des invocations multiples de
 *     {@code x.equals(y)} retournent de manière cohérente {@code true}
 *     ou de manière cohérente {@code false}, à condition que
 *     aucune information utilisée dans les comparaisons de {@code equals} sur les
 *     objets ne soit modifiée.
 * Pour toute valeur de référence non nulle {@code x},
 *     {@code x.equals(null)} devrait retourner {@code false}.
 * 
 * 
 * La méthode {@code equals} pour la classe {@code Object} implémente
 * la relation d'équivalence possible la plus discriminante sur les objets;
 * c'est-à-dire, pour toute valeur de référence non nulle {@code x} et
 * {@code y}, cette méthode retourne {@code true} si et seulement
 * si {@code x} et {@code y} se réfèrent au même objet
 * ({@code x == y} a la valeur {@code true}).
 * 

alors que :

Arrays.equals(array1, array2);

/**
 * Renvoie true si les deux tableaux spécifiés d'objets sont
 * égaux l'un à l'autre. Les deux tableaux sont considérés comme égaux si
 * les deux tableaux contiennent le même nombre d'éléments, et tous les
 * paires correspondantes d'éléments dans les deux tableaux sont égales. Deux objets e1
 * et e2 sont considérés comme égaux si (e1==null ? e2==null
 * : e1.equals(e2)). En d'autres termes, les deux tableaux sont égaux si
 * ils contiennent les mêmes éléments dans le même ordre. De plus, deux références de tableau
 * sont considérées comme égales si les deux sont null.
 *
 * @param a un tableau à tester pour l'égalité
 * @param a2 l'autre tableau à tester pour l'égalité
 * @return true si les deux tableaux sont égaux
 */
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

7voto

Adam Zalcman Points 13198

Les tableaux héritent de equals() de Object et ne renvoient donc vrai que si on compare un tableau avec lui-même.

En revanche, Arrays.equals compare les éléments des tableaux.

Ce morceau de code explique la différence:

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

Voir également Arrays.equals(). Un autre méthode statique pourrait également être utile: Arrays.deepEquals().

0 votes

Arrays.equals compare les éléments des tableaux

1voto

Michael Borgwardt Points 181658

La méthode equals() des tableaux est héritée de Object, elle ne regarde donc pas le contenu des tableaux, elle considère uniquement chaque tableau égal à lui-même.

Les méthodes Arrays.equals() comparent effectivement le contenu des tableaux. Il existe des surcharges pour tous les types primitifs, et celle pour les objets utilise les propres méthodes equals() des objets.

2 votes

Vous dites "contenu des tableaux", est-ce que cela inclut également les tableaux multidimensionnels ?

1 votes

@AlanFoster: non. Les tableaux multidimensionnels sont des tableaux de tableaux, ce qui signifie qu'ils invoqueront la méthode Arrays.equals(Object[], Object[]), qui appelle les méthodes equals() des sous-tableaux

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X