Is there a way to check if two Collections contain the same elements, independent of order?

44,407

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 Multisets 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))
Share:
44,407

Related videos on Youtube

Jorn
Author by

Jorn

hi :)

Updated on November 21, 2020

Comments

  • Jorn
    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 like Iterables.elementsEqual(), but that does account for ordering) and JUnit (assertEquals() obviously just calls equals() 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 take Iterables, but I'm also fine with simply taking Collections Such a method would of course take into account any duplicate elements in the collection (so it can't simply test for containsAll()).

    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
    Jorn over 14 years
    That 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
    Saurabh over 14 years
    This 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
    Jorn over 14 years
    True, but I do care about duplicates (as the question now states as well)
  • Jorn
    Jorn over 14 years
    This does appear to be the most efficient (and simple) solution I've seen so far.
  • Jorn
    Jorn over 14 years
    I'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
    Stephen C over 14 years
    @Jorn: if you want the answer "yes", then you won't get it :-)
  • Kevin Bourrillion
    Kevin Bourrillion over 14 years
    Jorn: 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
    3urdoch about 11 years
    Check 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
    Chris Gonzales almost 11 years
    In case you do not want to use Apache (or you can't) you can always do: collection1.containsAll(collection2) && collection2.containsAll(collection1)
  • Wesley Porter
    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.