views:

176

answers:

4

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.

A: 

If you want to ignore order, then how about testing sets for equality?

new HashSet(c1).equals(new HashSet(c2))
newacct
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.
Jorn
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.
finnw
True, but I do care about duplicates (as the question now states as well)
Jorn
+6  A: 

This is three method calls and uses Google Collections, 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.

finnw
This does appear to be the most efficient (and simple) solution I've seen so far.
Jorn
@Jorn: I thought you said you weren't asking how to implement this ...
Stephen C
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.
Jorn
@Jorn: if you want the answer "yes", then you won't get it :-)
Stephen C
Yeah, I was afraid of that...
Jorn
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!
Kevin Bourrillion
+2  A: 

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.

Well, the answer is no, AFAIK.

The most likely reason is that it is difficult to define an intuitive and consistent semantic for the 3 methods equals(Collection, Collection), equals(Set, Set) and equals(List, List). Another reason is that most applications/algorithms use either List or Set rather than Collection, and hence there is not much call for comparing Collections in the way you suggest.

Stephen C
+3  A: 

Apache commons-collections has CollectionUtils#isEqualCollection:

Returns true iff the given Collections contain exactly the same elements with exactly the same cardinality.

That is, iff 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.

Cowan