Quelle est la manière la plus simple de trouver si deux listes contiennent exactement les mêmes éléments dans les bibliothèques Java standard?
Peu importe que les deux listes soient la même instance ou non, et peu importe si le paramètre de type des listes est différent.
par exemple
List list1
List<String> list2;
// ... construct etc
list1.add("A");
list2.add("A");
// the function, given these two lists, should return true
Il y a probablement quelque chose qui me regarde en face, je sais :-)
EDIT: Pour clarifier, je cherchais les mêmes éléments EXACT et nombre d'éléments, dans l'ordre.
java
collections
Grundlefleck
la source
la source
Réponses:
Si vous vous souciez de la commande, utilisez simplement la méthode equals:
Du javadoc:
Si vous souhaitez vérifier indépendamment de l'ordre, vous pouvez copier tous les éléments dans les ensembles et utiliser des égaux sur les ensembles résultants:
Une limitation de cette approche est qu'elle ignore non seulement l'ordre, mais également la fréquence des éléments en double. Par exemple, si
list1
était ["A", "B", "A"] etlist2
était ["A", "B", "B"], l'Set
approche les considérerait comme égaux.Si vous devez être insensible à la commande mais sensible à la fréquence des doublons, vous pouvez soit:
la source
a = [x, y, x]
etb = [x, y, z]
ensuite les tailles sont égales etb.containsAll(a)
retourne vrai, maisb
contient un élément nona
.J'ai posté un tas de choses dans les commentaires, je pense que cela mérite sa propre réponse.
Comme tout le monde le dit ici, l'utilisation de equals () dépend de l'ordre. Si vous ne vous souciez pas de la commande, vous avez 3 options.
Option 1
Utilisez
containsAll()
. Cette option n'est pas idéale, à mon avis, car elle offre les pires performances, O (n ^ 2).Option 2
Il existe deux variantes:
2a) Si vous ne vous souciez pas de maintenir l'ordre de vos listes ... utilisez-les
Collections.sort()
sur les deux listes. Utilisez ensuite leequals()
. Il s'agit de O (nlogn), car vous effectuez deux sortes, puis une comparaison O (n).2b) Si vous devez maintenir l'ordre des listes, vous pouvez d'abord copier les deux listes. ALORS vous pouvez utiliser la solution 2a sur les deux listes copiées. Cependant, cela peut ne pas être attrayant si la copie est très coûteuse.
Cela mène à:
Option 3
Si vos exigences sont les mêmes que celles de la partie 2b , mais la copie est trop chère. Vous pouvez utiliser un TreeSet pour faire le tri pour vous. Videz chaque liste dans son propre TreeSet. Il sera trié dans l'ensemble et les listes originales resteront intactes. Effectuez ensuite une
equals()
comparaison sur les deuxTreeSet
art. LeTreeSets
s peut être construit en temps O (nlogn), et leequals()
est O (n).Faites votre choix :-).
EDIT: J'ai presque oublié la même mise en garde que Laurence Gonsalves souligne. L'implémentation TreeSet éliminera les doublons. Si vous vous souciez des doublons, vous aurez besoin d'une sorte de multiset trié.
la source
a.containsAll(b) && b.containsAll(a)
Si vous utilisez (ou êtes heureux d'utiliser) des collections Apache Commons, vous pouvez utiliser CollectionUtils.isEqualCollection qui "renvoie vrai si les collections données contiennent exactement les mêmes éléments avec exactement les mêmes cardinalités."
la source
Très tard pour la fête mais je voulais ajouter ce contrôle de sécurité nul:
la source
Je sais que c'est un vieux fil, mais aucune des autres réponses n'a complètement résolu mon cas d'utilisation (je suppose que Guava Multiset pourrait faire la même chose, mais il n'y a pas d'exemple ici). Veuillez excuser ma mise en forme. Je suis encore nouveau pour poster sur l'échange de pile. De plus, faites-moi savoir s'il y a des erreurs
Disons que vous avez
List<T>
a etList<T>
b et que vous voulez vérifier s'ils sont égaux aux conditions suivantes:1) O (n) durée de fonctionnement attendue
2) L'égalité est définie comme: Pour tous les éléments dans a ou b, le nombre de fois où l'élément apparaît dans a est égal au nombre de fois où l'élément apparaît dans b. L'égalité des éléments est définie par T.equals ()
Le temps d'exécution est O (n) car nous effectuons des insertions O (2 * n) dans une table de hachage et des sélections de table de hachage O (3 * n). Je n'ai pas entièrement testé ce code, alors attention :)
la source
Essayez cette version qui ne nécessite pas que l'ordre soit le même, mais qui prend en charge plusieurs de la même valeur. Ils ne correspondent que si chacun a la même quantité de n'importe quelle valeur.
la source
La méthode equals sur List fera cela, les listes sont ordonnées, donc pour être égales, deux listes doivent avoir les mêmes éléments dans le même ordre.
la source
Solution au cas où deux listes ont les mêmes éléments mais un ordre différent:
la source
removeAll()
place decontainsAll()
(si je comprends bien, si listTwo contient des doublons qui ne sont contenus qu'une seule fois dans listOne, l'approche containsAll () rapporterait à tort les listes comme égales).La réponse de Tom est excellente, je suis entièrement d'accord avec ses réponses!
Un aspect intéressant de cette question est de savoir si vous avez besoin du
List
type lui-même et de son ordre inhérent.Sinon, vous pouvez dégrader en
Iterable
ouCollection
ce qui vous donne une certaine flexibilité pour passer autour des structures de données qui sont triées au moment de l'insertion, plutôt qu'au moment où vous voulez vérifier.Si la commande n'a jamais d'importance (et que vous n'avez pas d'éléments en double), envisagez d'utiliser a
Set
.Si l'ordre importe mais est défini par le temps d'insertion (et que vous n'avez pas de doublons), considérez un
LinkedHashSet
qui est comme un TreeSet mais est ordonné par le temps d'insertion (les doublons ne sont pas comptés). Cela vous donne également unO(1)
accès amorti instantanémentO(log n)
.la source
Exemple de code:
la source
En plus de la réponse de Laurence, si vous souhaitez également la rendre null-safe:
la source
if (list1 == null) return list2==null; if (list2 == null) return false;
Si votre liste contient une classe MyClass personnalisée, cette classe doit remplacer la
equals
fonction.Remarque: si vous souhaitez tester égal sur un java.util.Set plutôt que sur un
java.util.List
, votre objet doit remplacer lahashCode
fonction.la source
List.equals ()
http://java.sun.com/j2se/1.5/docs/api/java/util/List.html#equals(java.lang.Object)
la source
Vous pouvez utiliser la bibliothèque org.apache.commons.collections d'Apache: http://commons.apache.org/collections/apidocs/org/apache/commons/collections/ListUtils.html
la source
Vérifiez que les deux listes ne sont pas nulles. Si leurs tailles sont différentes, ces listes ne sont pas égales. Créez des cartes composées des éléments des listes sous forme de clés et de leurs répétitions sous forme de valeurs et comparez les cartes.
Hypothèses, si les deux listes sont nulles, je les considère égales.
Veuillez noter que les méthodes égales doivent être correctement définies pour ces objets. https://stackoverflow.com/a/24814634/4587961
la source
[x, x, y]
vs[x, y, y]
retournerait vrai avec votre implémentation.Cela dépend de la classe List concrète que vous utilisez. La classe abstraite AbstractCollection a une méthode appelée containsAll (Collection) qui prend une autre collection (une List est une collection) et:
Donc, si une ArrayList est passée, vous pouvez appeler cette méthode pour voir si elles sont exactement les mêmes.
La raison de containsAll () est qu'il parcourt la première liste à la recherche de la correspondance dans la deuxième liste. Donc, s'ils sont en panne, equals () ne le ramassera pas.
EDIT: Je veux juste faire un commentaire ici sur le temps de fonctionnement amorti de l'exécution des différentes options proposées. Le temps de course est-il important? Sûr. Est-ce la seule chose à considérer? Non.
Le coût de la copie de CHAQUE élément à partir de vos listes dans d'autres listes prend du temps, et il prend également une bonne partie de la mémoire (doublant effectivement la mémoire que vous utilisez).
Donc, si la mémoire de votre machine virtuelle Java n'est pas un problème (ce qu'elle devrait généralement être), vous devez toujours prendre en compte le temps qu'il faut pour copier chaque élément de deux listes dans deux TreeSets. N'oubliez pas qu'il trie chaque élément au fur et à mesure qu'il y entre.
Mon dernier conseil? Vous devez prendre en compte votre ensemble de données et le nombre d'éléments que vous avez dans votre ensemble de données, ainsi que la taille de chaque objet de votre ensemble de données avant de pouvoir prendre une bonne décision ici. Jouez avec eux, créez-en un dans chaque sens et voyez lequel tourne le plus vite. C'est un bon exercice.
la source