diff --git a/src/main/java/org/apache/commons/collections/CollectionUtils.java b/src/main/java/org/apache/commons/collections/CollectionUtils.java index 5806b8703..7e6ab4bfc 100644 --- a/src/main/java/org/apache/commons/collections/CollectionUtils.java +++ b/src/main/java/org/apache/commons/collections/CollectionUtils.java @@ -71,6 +71,14 @@ public class CollectionUtils { return getFreq(obj, cardinalityB); } + public int sizeA() { + return cardinalityA.size(); + } + + public int sizeB() { + return cardinalityB.size(); + } + private final int getFreq(final Object obj, final Map freqMap) { final Integer count = freqMap.get(obj); if (count != null) { @@ -284,11 +292,13 @@ public class CollectionUtils { /** * Returns true iff all elements of {@code coll2} are also contained - * in {@code coll1}. + * in {@code coll1}. The cardinality of values in {@code coll2} is not taken into account, + * which is the same behavior as {@link Collection#containsAll(Collection)}. *

* In other words, this method returns true iff the * {@link #intersection} of coll1 and coll2 has the same cardinality as - * {@code coll2}. In case {@code coll2} is empty, {@code true} will be returned. + * the set of unique values from {@code coll2}. In case {@code coll2} is empty, {@code true} + * will be returned. *

* This method is intended as a replacement for {@link Collection#containsAll(Collection)} * with a guaranteed runtime complexity of {@code O(n)}. Depending on the type of @@ -298,16 +308,19 @@ public class CollectionUtils { * @param coll1 the first collection, must not be null * @param coll2 the second collection, must not be null * @return true iff the intersection of the collections has the same cardinality - * of the second collection + * as the set of unique elements from the second collection * @since 4.0 - * @see #intersection */ public static boolean containsAll(final Collection coll1, final Collection coll2) { if (coll2.isEmpty()) { return true; } else { - Collection result = CollectionUtils.intersection(coll1, coll2); - return result.size() == coll2.size(); + final SetOperationCardinalityHelper helper = + new SetOperationCardinalityHelper(coll1, coll2); + for (final Object obj : helper) { + helper.setCardinality(obj, helper.min(obj)); + } + return helper.list().size() == helper.sizeB(); } } diff --git a/src/test/java/org/apache/commons/collections/CollectionUtilsTest.java b/src/test/java/org/apache/commons/collections/CollectionUtilsTest.java index be066eb48..75d75c845 100644 --- a/src/test/java/org/apache/commons/collections/CollectionUtilsTest.java +++ b/src/test/java/org/apache/commons/collections/CollectionUtilsTest.java @@ -252,6 +252,10 @@ public class CollectionUtilsTest extends MockTestCase { final Collection odds = new ArrayList(2); odds.add("1"); odds.add("3"); + final Collection multiples = new ArrayList(3); + multiples.add("1"); + multiples.add("3"); + multiples.add("1"); assertTrue("containsAll({1},{1,3}) should return false.", !CollectionUtils.containsAll(one, odds)); assertTrue("containsAll({1,3},{1}) should return true.", CollectionUtils.containsAll(odds, one)); @@ -267,6 +271,10 @@ public class CollectionUtilsTest extends MockTestCase { assertTrue("containsAll({1,3},{}) should return true.", CollectionUtils.containsAll(odds, empty)); assertTrue("containsAll({},{1,3}) should return false.", !CollectionUtils.containsAll(empty, odds)); assertTrue("containsAll({},{}) should return true.", CollectionUtils.containsAll(empty, empty)); + + assertTrue("containsAll({1,3},{1,3,1}) should return true.", CollectionUtils.containsAll(odds, multiples)); + assertTrue("containsAll({1,3,1},{1,3,1}) should return true.", CollectionUtils.containsAll(odds, odds)); + assertTrue("containsAll({1,3,1},{1,3,1}) should return true.", CollectionUtils.containsAll(odds, odds)); } @Test