Search code examples
javacollectionsset

Java Set.containsAll returns true for empty list


The containsAll method in the AbstractCollection class is implemented as below:

public boolean containsAll(Collection<?> c) {
    for (Object e : c)
        if (!contains(e))
            return false;
    return true;
}

It doesn't check for empty c and still returns true for the below testcase:

@Test
public void testContainsAllOfHashSet() {
    List<String> reasons = new LinkedList<>();
    Set<String> allReasons = new HashSet<>();
    allReasons.add("Java");
    Assert.assertFalse(allReasons.containsAll(reasons));
}

The above test is failing as containsAll is returning true for empty reasons. allreasons contains at least one element and definitely no empty elements are there. Therefore, the above test case should pass. Let me know if my understanding here is wrong.


Solution

  • x.containsAll(y) returns true if x contains all the elements in y, which in this case, is a vacuous truth.

    It's easier to understand if you rephrase the definition in negative terms - x.containsAll(y) returns true if y has no element that is not contained in x. If y is empty it has no elements at all, and specifically cannot have any element that isn't contained in x.

    In short, in your case allReasons.containsAll(reasons) should return true, and your current assertion is wrong.