Jetez également un œil à java.util.Arrays.deepEquals (Object [] a1, Object [] a2)
ultraon
Réponses:
299
array1.equals(array2)est le même que array1 == array2, c'est-à-dire est-ce le même tableau. Comme le souligne @alf, ce n'est pas ce que la plupart des gens 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 l'utiliser Arrays.toString(array).
Notez que Arrays.equals()cela ne fonctionne pas comme prévu pour les tableaux multidimensionnels, il compare uniquement les éléments de la 1ère dimension pour l'égalité de référence. Apache commons ArrayUtils.isEqualsfonctionne avec des tableaux multidimensionnels.
Adam Parkin
4
Je suis stupéfait. Y a-t-il une raison pour que array.equals soit implémenté pour comparer les pointeurs plutôt que pour comparer la longueur et chaque objet?
Lake
2
@Lake compare la longueur du tableau et les objets contenus, mais ce qu'il ne fait pas est une comparaison approfondie. Le fait égal fonctionne comme prévu pour les tableaux est cassé, cela ne devrait pas être un problème en premier lieu.
@JeewanthaSamaraweera qui est la définition de cette méthode, mais car .equalselle ne compare pas le contenu, c'est pourquoi vous avez besoin de cette méthode.
Peter Lawrey
86
C'est un problème tristement célèbre: .equals()car les tableaux sont gravement cassés, ne les utilisez jamais.
Cela dit, ce n'est pas "cassé" comme dans "quelqu'un l'a fait de manière vraiment erronée" - il fait juste ce qui est défini et pas ce qui est généralement attendu. Donc pour les puristes: c'est parfaitement bien, et cela signifie aussi, ne l'utilisez pas, jamais.
Maintenant, le comportement attendu de equalsest de comparer les données. Le comportement par défaut est de comparer l'identité, car elle Objectn'a pas de données (pour les puristes: oui, mais ce n'est pas la question); l'hypothèse est, si vous equalsen avez besoin dans les sous-classes, vous l'implémenterez. Dans les tableaux, il n'y a pas d'implémentation pour vous, vous n'êtes donc pas censé l'utiliser.
Donc la différence est que ça Arrays.equals(array1, array2)marche comme vous vous attendez (c.-à-d. Compare le contenu), array1.equals(array2)revient à la Object.equalsmise en œuvre, qui à son tour compare l'identité, et donc mieux remplacée par ==(pour les puristes: oui, je sais null).
Le problème est que même Arrays.equals(array1, array2)vous mordra fort si les éléments du tableau ne sont pas equalscorrectement implémentés . C'est une déclaration très naïve, je sais, mais il y a un cas très peu évident: considérer un tableau 2D.
Le tableau 2D en Java est un tableau de tableaux, et les tableaux equalssont cassés (ou inutiles si vous préférez), donc Arrays.equals(array1, array2)ne fonctionneront pas comme prévu sur les tableaux 2D.
Un tableau a-t-il une implémentation personnalisée pour equals()? Je pensais que ce n'était pas remplacé par Object.
Martijn Courteaux
@MichaelBorgwardt c'est une bibliothèque système, avec une méthode qui ne fait pas ce qui est dit dans le javadoc. Cela me semble assez cassé. Cela dit, je reconnais que c'est une déclaration très défendable, mais je pense que "c'est cassé" est mieux mémorisé, et donc il est beaucoup plus commode de penser de cette façon.
alf
@MartijnCourteaux c'est exactement le problème :)
alf
3
Pour les tableaux de tableaux, vous avez besoin Arrays.deepEquals--- c'est ce qui someArray.equalsaurait dû faire tout au long. (Connexes:. Objects.deepEquals)
Kevin J. Chase
16
Regardez à l'intérieur de la mise en œuvre des deux méthodes pour les comprendre en profondeur:
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
*/publicboolean equals(Object obj){return(this== obj);}
tandis que:
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
*/publicstaticboolean equals(Object[] a,Object[] a2){if(a==a2)returntrue;if(a==null|| a2==null)returnfalse;int length = a.length;if(a2.length != length)returnfalse;for(int i=0; i<length; i++){Object o1 = a[i];Object o2 = a2[i];if(!(o1==null? o2==null: o1.equals(o2)))returnfalse;}returntrue;}
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 arrivait parfois que quelqu'un soumette un APAR (rapport de bogue) sur un comportement inattendu d'une commande CMS, et IBM répondait NOTABUG: la commande fait ce pour quoi elle a été conçue (et ce que dit la documentation).
SHARE a trouvé un contre-argument: BAD - Broken As Designed. Je pense que cela pourrait s'appliquer à cette implémentation d'égaux pour les tableaux.
Il n'y a rien de mal à l'implémentation d'Object.equals. L'objet n'a aucun membre de données, il n'y a donc rien à comparer. Deux "Objects" 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 contiennent des données, et vous vous attendez à une comparaison (via égal) pour comparer les données. Idéalement, comme le fait Arrays.deepEquals, mais au moins comme le fait Arrays.equals (comparaison superficielle des éléments).
Le problème est donc que le tableau (en tant qu'objet intégré) ne remplace pas Object.equals. La chaîne (en tant que classe nommée) ne override Object.equals et donner le résultat que vous attendez.
Les autres réponses données sont correctes: [...]. É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 [...] égalait réellement les éléments? Pas beaucoup, je suppose, mais plus de zéro.
vérifiez si les deux tableaux contiennent le même nombre d'éléments et si toutes les paires d'éléments correspondantes dans les deux tableaux sont égales.
Le array1.equals(array2):
comparer l'objet à un autre objet et ne renvoyer true que si la référence des deux objets est égale à celle du Object.equals()
Le equals()des tableaux est hérité de Object, donc il ne regarde pas le contenu des tableaux, il ne considère que chaque tableau égal à lui-même.
Les Arrays.equals()méthodes ne se comparent le contenu des tableaux. Il y a des surcharges pour tous les types primitifs, et celle pour les objets utilise les propres equals()méthodes des objets .
vous dites "contenu des tableaux", cela signifie-t-il aussi des tableaux multidimensionnels?
AlanFoster
@AlanFoster: non. Les tableaux multidimensionnels sont des tableaux de tableaux, ce qui signifie qu'ils utilisent la méthode Arrays.equals (Object [], Object []) qui sera appelée, ce qui appelle les méthodes equals () des sous-tableaux
Michael Borgwardt
0
import java.util.Arrays;publicclassArrayDemo{publicstaticvoid main(String[] args){// initializing three object arraysObject[] array1 =newObject[]{1,123};Object[] array2 =newObject[]{1,123,22,4};Object[] array3 =newObject[]{1,123};// comparing array1 and array2boolean retval=Arrays.equals(array1, array2);System.out.println("array1 and array2 equal: "+ retval);System.out.println("array1 and array2 equal: "+ array1.equals(array2));// comparing array1 and array3boolean retval2=Arrays.equals(array1, array3);System.out.println("array1 and array3 equal: "+ retval2);System.out.println("array1 and array3 equal: "+ array1.equals(array3));}}
Voici la sortie:
array1 and array2 equal:false
array1 and array2 equal:false
array1 and array3 equal:true
array1 and array3 equal:false
Voyant ce genre de problème, je choisirais personnellement Arrays.equals(array1, array2)selon votre question pour éviter toute confusion.
Cela semble correct mais sur les tableaux, l'ordre des éléments est également important. Par exemple, s'il y a un autre tableau Object [] array4 = new Object [] {123, 1}; avec Arrays.equals (array3, array4), il retournera false.
Réponses:
array1.equals(array2)
est le même quearray1 == array2
, c'est-à-dire est-ce le même tableau. Comme le souligne @alf, ce n'est pas ce que la plupart des gens 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 l'utiliserArrays.toString(array)
.la source
Arrays.equals()
cela ne fonctionne pas comme prévu pour les tableaux multidimensionnels, il compare uniquement les éléments de la 1ère dimension pour l'égalité de référence. Apache commonsArrayUtils.isEquals
fonctionne avec des tableaux multidimensionnels.Arrays.deepEquals(Object[], Object[])
..equals
elle ne compare pas le contenu, c'est pourquoi vous avez besoin de cette méthode.C'est un problème tristement célèbre:
.equals()
car les tableaux sont gravement cassés, ne les utilisez jamais.Cela dit, ce n'est pas "cassé" comme dans "quelqu'un l'a fait de manière vraiment erronée" - il fait juste ce qui est défini et pas ce qui est généralement attendu. Donc pour les puristes: c'est parfaitement bien, et cela signifie aussi, ne l'utilisez pas, jamais.
Maintenant, le comportement attendu de
equals
est de comparer les données. Le comportement par défaut est de comparer l'identité, car elleObject
n'a pas de données (pour les puristes: oui, mais ce n'est pas la question); l'hypothèse est, si vousequals
en avez besoin dans les sous-classes, vous l'implémenterez. Dans les tableaux, il n'y a pas d'implémentation pour vous, vous n'êtes donc pas censé l'utiliser.Donc la différence est que ça
Arrays.equals(array1, array2)
marche comme vous vous attendez (c.-à-d. Compare le contenu),array1.equals(array2)
revient à laObject.equals
mise en œuvre, qui à son tour compare l'identité, et donc mieux remplacée par==
(pour les puristes: oui, je saisnull
).Le problème est que même
Arrays.equals(array1, array2)
vous mordra fort si les éléments du tableau ne sont pasequals
correctement implémentés . C'est une déclaration très naïve, je sais, mais il y a un cas très peu évident: considérer 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), doncArrays.equals(array1, array2)
ne fonctionneront pas comme prévu sur les tableaux 2D.J'espère que cela pourra aider.
la source
equals()
? Je pensais que ce n'était pas remplacé par Object.Arrays.deepEquals
--- c'est ce quisomeArray.equals
aurait dû faire tout au long. (Connexes:.Objects.deepEquals
)Regardez à l'intérieur de la mise en œuvre des deux méthodes pour les comprendre en profondeur:
tandis que:
la source
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 arrivait parfois que quelqu'un soumette un APAR (rapport de bogue) sur un comportement inattendu d'une commande CMS, et IBM répondait NOTABUG: la commande fait ce pour quoi elle a été conçue (et ce que dit la documentation).
SHARE a trouvé un contre-argument: BAD - Broken As Designed. Je pense que cela pourrait s'appliquer à cette implémentation d'égaux pour les tableaux.
Il n'y a rien de mal à l'implémentation d'Object.equals. L'objet n'a aucun membre de données, il n'y a donc rien à comparer. Deux "Objects" 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 contiennent des données, et vous vous attendez à une comparaison (via égal) pour comparer les données. Idéalement, comme le fait Arrays.deepEquals, mais au moins comme le fait Arrays.equals (comparaison superficielle des éléments).
Le problème est donc que le tableau (en tant qu'objet intégré) ne remplace pas Object.equals. La chaîne (en tant que classe nommée) ne override Object.equals et donner le résultat que vous attendez.
Les autres réponses données sont correctes: [...]. É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 [...] égalait réellement les éléments? Pas beaucoup, je suppose, mais plus de zéro.
la source
Les tableaux hérités
equals()
deObject
et donc compare ne retournent true que si un tableau est comparé à lui-même.En revanche,
Arrays.equals
compare les éléments des tableaux.Cet extrait élucide la différence:
Voir aussi
Arrays.equals()
. Une autre méthode statique , il peut également intéresser:Arrays.deepEquals()
.la source
Le
Arrays.equals(array1, array2)
:vérifiez si les deux tableaux contiennent le même nombre d'éléments et si toutes les paires d'éléments correspondantes dans les deux tableaux sont égales.
Le
array1.equals(array2)
:comparer l'objet à un autre objet et ne renvoyer true que si la référence des deux objets est égale à celle du
Object.equals()
la source
Le
equals()
des tableaux est hérité deObject
, donc il ne regarde pas le contenu des tableaux, il ne considère que chaque tableau égal à lui-même.Les
Arrays.equals()
méthodes ne se comparent le contenu des tableaux. Il y a des surcharges pour tous les types primitifs, et celle pour les objets utilise les propresequals()
méthodes des objets .la source
Voici la sortie:
Voyant ce genre de problème, je choisirais personnellement
Arrays.equals(array1, array2)
selon votre question pour éviter toute confusion.la source