web-dev-qa-db-fra.com

Égalité entre 2 HashMap

Dans la méthode equals () de ma classe, j'utilise une variable HashMap d'instance privée pour comparer l'égalité. Cependant, 2 objets différents montrent toujours être égaux lors de la comparaison de leurs variables HashMap. De plus amples recherches m'ont amené au lien: Lien ici . Cependant, il dit simplement que la raison pour laquelle HashMap1.equals (HashMap2) ne fonctionne pas est parce que "apparemment les tableaux de Java ne peuvent pas être testés pour l'égalité sans écrire un code personnalisé."

Je n'ai pas compris cette raison. Quelqu'un peut-il me guider vers une raison détaillée?

22
name_masked

La méthode equals sur un type de tableau Java est équivalente à ==, Car Java ne remplacent pas Object.equals.

Si vous souhaitez comparer des tableaux "par valeur", vous devez soit utiliser la méthode Java.util.Arrays.equals(...) appropriée, soit l'implémenter vous-même.

Si votre HashMap utilise des tableaux comme clés ou valeurs, il va appeler la méthode equals du tableau pour tester si les clés et/ou les valeurs sont les mêmes entre deux cartes. Cela ferait que HashMap.equals Se comporterait étrangement (de votre point de vue). C'est ce que dit l'article lié. Cependant, la sémantique des tableaux niquement affecte l'égalité HashMap si vous utilisez des tableaux comme classes de clés ou de valeurs. Si vous ne le faites pas, alors HashMap::equals Devrait fonctionner comme prévu.

Les javadocs pour l'égalité sur les classes Map sont un peu impliqués, mais ils se résument essentiellement à prendre les deux ensembles d'entrées, à comparer leurs tailles, puis à faire s1.containsAll(s2). Bien sûr, cela coûte cher, mais cela devrait fonctionner pour toutes les classes Map qui implémentent correctement l'interface Map.


Notez que l'utilisation de tableaux comme clés pour les cartes est une mauvaise idée pour plusieurs raisons:

  1. La sémantique du tableau equals et hashCode est incorrecte pour un HashMap dans la plupart des scénarios. Pour la plupart des cas d'utilisation, vous avez besoin de la carte pour comparer les clés par valeur et non par identité d'objet.
  2. Les tableaux sont mutables. Si nous supposions qu'il y avait une solution de contournement pour le problème equals/hashcode, vous pourriez toujours casser les invariants d'une carte en modifiant une clé de tableau.
31
Stephen C

L'article est juste. Les Hashmaps peuvent être comparés en toute sécurité à l'aide de la méthode equals () tant qu'il est possible de comparer les objets clés et les objets de valeur à l'aide de la même méthode. Dans l'article, les valeurs de mappage sont des tableaux, qui n'implémentent pas equals () comme prévu. À la place, ArrayList aurait résolu le problème.

11
Eyal Schneider

Native Java n'ont pas de fonction .equals (). Donc, si les valeurs de votre table de hachage (ou les clés, je suppose) sont des tableaux, HashMap.equals () échouera. Je le soupçonne retomber sur Object.equals () qui vérifie simplement si les deux objets sont en fait le même objet.

// something like this
class Object {
  public boolean equals( Object o) {
    return this == o;
  }
}

Vous pouvez contourner le problème en utilisant une variante sur un conteneur plutôt qu'un tableau [], car les conteneurs ont leur propre .equals () qui appelle equals () sur les éléments successifs des conteneurs plutôt que de simplement vérifier s'ils sont la même référence . Le code d'une implémentation Collection.equals peut ressembler à ceci:

public boolean equals(Object o) {
  // sets never equal lists and visa versa
  if (o instanceof MyCollectionSubclass) {
    Iterator myIterator = iterator();
    Iterator theirIterator = ((Collection)o).iterator();
    while (myIterator.hasNext() && theirIterator.hasNext()) {
      Object myObj = myIterator.next();
      Object theirObj = theirIterator.next();
      if (!myObj.equals(theirObj)) {
        return false;
      }
    }
    // at least one will be false or we wouldn't have left the above while loop
    return myIterator.hasNext() == theirIterator.hasNext();
  }
  // not our class
  return false;
}

Cela peut produire une comparaison de valeur réelle en fonction de ce que fait le contenu de la collection lorsque vous appelez leur equals().

4
Mark Storer

L'égalité des tableaux de Java ne peut pas être testée sans écrire un code personnalisé

Ceci est juste une façon compliquée de dire que Java ne remplacent pas Object.equals(). Par conséquent, si vous les comparez en utilisant equals() (qui est ce que le equals méthodes de toutes les classes de collection), vous obtenez "égalité d'instance", au lieu de "égalité de valeur".

C'est vraiment juste un cas particulier des différentes façons dont equals fonctionne selon qu'il a été remplacé ou non.

2
sleske