Is there a way to check if two Collections contain the same elements, independent of order?
Solution 1
Apache commons-collections has CollectionUtils#isEqualCollection:
Returns true if the given Collections contain exactly the same elements with exactly the same cardinality.
That is, if the cardinality of e in a is equal to the cardinality of e in b, for each element e in a or b.
Which is, I think, exactly what you're after.
Solution 2
This is three method calls and uses Google CollectionsGuava, but is possibly as simple as it gets:
HashMultiset.create(c1).equals(HashMultiset.create(c2));
Creating the temporary Multiset
s may appear wasteful, but to compare the collections efficiently you need to index them somehow.
Solution 3
If you want to ignore order, then how about testing sets for equality?
new HashSet(c1).equals(new HashSet(c2))
Related videos on Youtube
Comments
-
Jorn over 3 years
I've been looking for a method that operates like
Arrays.equals(a1, a2)
, but ignoring the element order. I haven't been able to find it in either Google Collections (something likeIterables.elementsEqual()
, but that does account for ordering) and JUnit (assertEquals()
obviously just callsequals()
on the Collection, which depends on the Collection implementation, and that's not what I want) It would be best if such a method would takeIterable
s, but I'm also fine with simply takingCollection
s Such a method would of course take into account any duplicate elements in the collection (so it can't simply test forcontainsAll()
).Note that I'm not asking how to implement such a thing, I was just wondering if any of the standard Collections libraries have it.
-
Jorn over 14 yearsThat doesn't work, because it would throw away duplicate elements. Also, I'd have to create two new HashSets. I'd rather avoid creating new objects for this.
-
Saurabh over 14 yearsThis is fine if you don't care about duplicates, e.g. c1 = Arrays.asList(1, 1, 2), c2 = Arrays.asList(1, 2, 2) will be equal according to this expression.
-
Jorn over 14 yearsTrue, but I do care about duplicates (as the question now states as well)
-
Jorn over 14 yearsThis does appear to be the most efficient (and simple) solution I've seen so far.
-
Jorn over 14 yearsI'm not saying it's the solution I asked for, but I haven't seen an answer that provides me with a single method call to do this.
-
Stephen C over 14 years@Jorn: if you want the answer "yes", then you won't get it :-)
-
Kevin Bourrillion over 14 yearsJorn: the fact that you want to do this in the first place is a strong signal that you want one or both of these collections to be represented as Multisets in the first place. They cannot really logically be Lists if you don't care about their order. If you do represent both as Multisets, then guess what? You've got your single-method-call solution!
-
3urdoch about 11 yearsCheck out the CollectionUtils.isEqualCollection source code from @Cowan's answer and you will find this is exactly how it is done there but isEqualCollection is more expressive and therefore gets my vote. Of course if your not using commons-collections but you are using Guava then this may be a preferable option.
-
Chris Gonzales almost 11 yearsIn case you do not want to use Apache (or you can't) you can always do: collection1.containsAll(collection2) && collection2.containsAll(collection1)
-
Wesley Porter almost 10 years@ChrisGonzales, beware of that solution - it will return true for the following two collections: collection1 = [1, blah, 1, 4], collection2 = [1, blah, blah, 4]. Where those two collections are indeed not the same.