Si vous voulez simplement savoir si les ensembles sont égaux, la equals
méthode on AbstractSet
est implémentée à peu près comme ci-dessous:
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Collection c = (Collection) o;
if (c.size() != size())
return false;
return containsAll(c);
}
Notez comment il optimise les cas courants où:
- les deux objets sont les mêmes
- l'autre objet n'est pas du tout un ensemble, et
- les tailles des deux ensembles sont différentes.
Après cela, containsAll(...)
reviendra false
dès qu'il trouvera un élément dans l'autre ensemble qui n'est pas également dans cet ensemble. Mais si tous les éléments sont présents dans les deux ensembles, il devra tous les tester.
La pire des performances se produit donc lorsque les deux ensembles sont égaux mais pas les mêmes objets. Ce coût est généralement O(N)
ou O(NlogN)
dépend de la mise en œuvre de this.containsAll(c)
.
Et vous obtenez des performances proches du pire des cas si les ensembles sont grands et ne diffèrent que par un petit pourcentage des éléments.
METTRE À JOUR
Si vous êtes prêt à investir du temps dans une implémentation personnalisée, il existe une approche qui peut améliorer le cas «presque identique».
L'idée est que vous devez pré-calculer et mettre en cache un hachage pour l'ensemble complet afin de pouvoir obtenir la valeur de hachage actuelle de l'ensemble O(1)
. Ensuite, vous pouvez comparer le hashcode pour les deux ensembles comme une accélération.
Comment pourriez-vous implémenter un hashcode comme ça? Eh bien, si le hashcode défini était:
- zéro pour un ensemble vide, et
- le XOR de tous les hashcodes des éléments pour un ensemble non vide,
alors vous pouvez mettre à jour à moindre coût le hashcode mis en cache de l'ensemble chaque fois que vous avez ajouté ou supprimé un élément. Dans les deux cas, il vous suffit de XOR le hashcode de l'élément avec le hashcode actuel défini.
Bien sûr, cela suppose que les codes de hachage des éléments sont stables tandis que les éléments sont membres d'ensembles. Il suppose également que la fonction de hashcode des classes d'éléments donne une bonne répartition. En effet, lorsque les deux codes de hachage définis sont identiques, vous devez toujours revenir à la O(N)
comparaison de tous les éléments.
Vous pourriez pousser cette idée un peu plus loin ... du moins en théorie.
AVERTISSEMENT - Ceci est hautement spéculatif. Une "expérience de pensée" si vous le souhaitez.
Supposons que votre classe d'élément set ait une méthode pour renvoyer une somme de contrôle cryptographique pour l'élément. Maintenant, implémentez les sommes de contrôle de l'ensemble en XORing les sommes de contrôle retournées pour les éléments.
Qu'est-ce que cela nous achète?
Eh bien, si nous supposons qu'il ne se passe rien par dessous, la probabilité que deux éléments d'ensemble inégaux aient les mêmes sommes de contrôle de N bits est de 2 -N . Et la probabilité que 2 ensembles inégaux aient les mêmes sommes de contrôle de N bits est également de 2 -N . Donc, mon idée est que vous pouvez mettre equals
en œuvre comme:
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Collection c = (Collection) o;
if (c.size() != size())
return false;
return checksums.equals(c.checksums);
}
Selon les hypothèses ci-dessus, cela ne vous donnera la mauvaise réponse qu'une fois toutes les 2 -N . Si vous rendez N suffisamment grand (par exemple 512 bits), la probabilité d'une mauvaise réponse devient négligeable (par exemple environ 10 -150 ).
L'inconvénient est que le calcul des sommes de contrôle cryptographiques pour les éléments est très coûteux, d'autant plus que le nombre de bits augmente. Vous avez donc vraiment besoin d'un mécanisme efficace pour mémoriser les sommes de contrôle. Et cela pourrait être problématique.
Et l'autre inconvénient est qu'une probabilité d'erreur non nulle peut être inacceptable, quelle que soit la faible probabilité. (Mais si tel est le cas ... comment gérez-vous le cas où un rayon cosmique retourne un bit critique? Ou s'il retourne simultanément le même bit dans deux instances d'un système redondant?)