Problem:
Given two Collection<?>s, check if both contain the same elements.
- Assuming that the actual implementation of the collection is unknown
- Assuming that the elements do not occur in the same order
- Assuming that no element does occur twice in the same collection
Solution 1:
boolean equals = c1.containsAll(c2) && c2.containsAll(c1);
Solution 2:
boolean equals = new HashSet<?>(c1).equals(new HashSet<?>(c2));
I would assume Solution 2 to be more efficient (O(n)) than Solution 1 (O(n^2)).
Am I correct or did I miss something?
The Big O complexity of these is correct, Solution 1 involves iterating over one list (
O (n)) for each item in the other list, which isO (n^2). Solution 2 involves twoO (n)copies and iterating over one set (O (n)) and doingO (1).contains()checks on the other set. All told, that's justO (n).But depending on your constraints you can do better (not asymptotically better, just a better implementation).
Since we're assuming no duplicate elements, there's no need to do the second
.containsAll()check. Simply check they're the same size (which might beO (n), but it's still better than duplicating anO (n^2)check) then do the.containsAll().There's no need to convert
c2into aSet, since it will be iterated over anyways; just convertc1and use.containsAll().You can use
instanceof Setto test ifc1orc2is already aSet, and use that object's.containsAll()method; this will run inO (n)time even if the other object is not a set, and avoids the copying overhead that Solution 2 has.