est égal à vs Arrays.equals en Java

Lorsque vous comparez des tableaux en Java, existe-t-il des différences entre les deux instructions suivantes?

array1.equals(array2); Arrays.equals(array1, array2); 

Et si oui quels sont-ils?

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

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


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

C’est un problème infâme: .equals() pour les tableaux est cassé, mais ne l’utilisez jamais.

Cela dit, ce n’est pas “cassé” comme dans “quelqu’un l’a fait d’une manière vraiment fausse” – c’est juste faire ce qui est défini et pas ce qui est généralement attendu. Donc pour les puristes: c’est parfaitement bien, et ça veut aussi dire, ne l’utilisez jamais.

Maintenant, le comportement attendu pour les equals est de comparer les données. Le comportement par défaut consiste à comparer l’identité, car Object n’a pas de données (pour les puristes: oui, mais ce n’est pas le point); l’hypothèse est que, si vous avez besoin d’ equals à equals dans les sous-classes, vous l’implémenterez. Dans les baies, il n’y a pas d’implémentation pour vous, vous n’êtes donc pas censé l’utiliser.

Donc, la différence est que Arrays.equals(array1, array2) fonctionne comme prévu (c.-à-d. array1.equals(array2) contenu), array1.equals(array2) revient à l’implémentation d’ Object.equals , qui à son tour compare l’identité, et donc mieux remplacée par == (pour les puristes: oui je sais à propos de null ).

Le problème est que même Arrays.equals(array1, array2) va vous mordre si les éléments du tableau ne s’implémentent pas correctement. Je sais que c’est une affirmation très naïve, mais il y a un cas très important, moins évident que cela: considérez un tableau 2D.

Le tableau 2D en Java est un tableau de tableaux, et les tableaux equals sont cassés (ou inutiles si vous préférez), donc Arrays.equals(array1, array2) ne fonctionnera pas comme prévu sur les tableaux 2D.

J’espère que cela pourra aider.

Regardez à l’intérieur de la mise en œuvre des deux méthodes pour les comprendre profondément:

 array1.equals(array2); 
 /** * Indicates whether some other object is "equal to" this one. * 

* The {@code equals} method implements an equivalence relation * on non-null object references: *

    *
  • It is reflexive: for any non-null reference value * {@code x}, {@code x.equals(x)} should return * {@code true}. *
  • It is symmesortingc: 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}. *
  • It is transitive: 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}. *
  • It is consistent: 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. *
  • For any non-null reference value {@code x}, * {@code x.equals(null)} should return {@code false}. *
*

* 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}). *

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

tandis que:

 Arrays.equals(array1, array2); 
 /** * Returns true if the two specified arrays of Objects are * equal 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 e1 * and e2 are considered equal if (e1==null ? e2==null * : e1.equals(e2)). 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 null.

* * @param a one array to be tested for equality * @param a2 the other array to be tested for equality * @return true 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

Soupir. Dans les années 70, j’étais le “programmeur système” (sysadmin) d’un système IBM 370 et mon employeur était membre du groupe d’utilisateurs IBM SHARE. Il arrive parfois que quelqu’un soumette un APAR (rapport de bogue) sur un comportement inattendu de certaines commandes du CMS, et IBM réponde à NOTABUG: la commande fait ce pour quoi elle a été conçue (et ce que dit la documentation).

SHARE est venu avec un contre à ceci: MAUVAIS – cassé comme conçu. Je pense que cela pourrait s’appliquer à cette implémentation des égaux pour les tableaux.

Il n’y a rien de mal à l’implémentation d’Object.equals. L’object n’a aucun membre de données, il n’y a donc rien à comparer. Deux “Object” sont égaux si et seulement s’ils sont, en fait, le même Object (en interne, la même adresse et la même longueur).

Mais cette logique ne s’applique pas aux tableaux. Les tableaux ont des données et vous vous attendez à ce que la comparaison (via des équivalents) compare les données. Idéalement, la façon dont Arrays.deepEquals le fait, mais au moins comme Arrays.equals (comparaison superficielle des éléments).

Le problème est donc que le tableau (en tant qu’object intégré) ne remplace pas Object.equals. Ssortingng (en tant que classe nommée) remplace les Object.equals et donne le résultat attendu.

Les autres réponses données sont correctes: […]. Est égal à ([….]) compare simplement les pointeurs et non le contenu. Peut-être qu’un jour quelqu’un corrigera cela. Ou peut-être pas: combien de programmes existants se briseraient si […], égaux, comparaient réellement les éléments? Pas beaucoup, je pense, mais plus que zéro.

Les tableaux héritent de equals() d’ Object et par conséquent, compare uniquement renvoie true si l’on compare un tableau à lui-même.

D’autre part, Arrays.equals compare les éléments des tableaux.

Cet extrait élucide 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)); // prints false System.out.println(Arrays.equals(a1, a2)); // prints true 

Voir aussi Arrays.equals() . Une autre méthode statique peut également être intéressante: Arrays.deepEquals() .

Les Arrays.equals(array1, array2) :

vérifiez si les deux tableaux contiennent le même nombre d’éléments et toutes les paires d’éléments correspondantes dans les deux tableaux sont égales.

Le array1.equals(array2) :

comparer l’object à un autre object et renvoyer true uniquement si la référence des deux objects est égale à celle de l’object Object.equals()

L’ equals() des tableaux est hérité d’ Object , donc il ne regarde pas le contenu des arrays, il considère seulement chaque tableau comme égal à lui-même.

Les méthodes Arrays.equals() comparent le contenu des tableaux. Il y a des surcharges pour tous les types primitifs, et celui des objects utilise les méthodes equals() des objects.

 import java.util.Arrays; public class ArrayDemo { public static void main(Ssortingng[] 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)); } } 

Voici la sortie:

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

En voyant ce genre de problème, je choisirais personnellement Arrays.equals(array1, array2) selon votre question pour éviter toute confusion.