The javadocs for containsAll (in Collection) say:
Returns: true if this collection
contains all of the elements in the
specified collection
and for retainAll (in Collection):
Retains only the elements in this
collection that are contained in the
specified collection (optional
operation). In other words, removes
from this collection all of its
elements that are not contained in the
specified collection.
I read containsAll's contract to mean that calling a.containsAll(b) will return true, if and only if, calling a.contains(bElem) for each element bElem in b would return true. I would also take it to imply that a.containsAll(someEmptyCollection) would also return true. As you state the javadocs for AbstractCollection more explicitly state this:
This implementation iterates over the
specified collection, checking each
element returned by the iterator in
turn to see if it's contained in this
collection. If all elements are so
contained true is returned, otherwise
false.
I agree that the contact for Collection for containsAll sould be more explicit to avoid any possiblity for confusion. (And that the reading of the javadocs for AbstractCollection should NOT have been necessary to confirm ones understanding of Collection)
I would not have made an assumption with regard to number of duplicate elements after a call to retainAll. The stated contract in Collection (by my reading) doesn't imply either way how duplicates in either collection would be handled. Based on my reading of retainAll in collection multiple possible results of a.retainAll(b) are all reasonable:
- result contains 1 of each element that has at least one copy in both a and b
- result contains each element (including duplicates) that was in a, except those that are not in b
- or even, result contains somewhere between 1 and the number of copies found in a of each element in a, except those not in b.
I would have expected either #1 or #2, but would assume any of the the three to be legal based on the contract.
The javadocs for AbstractCollection confirm that it uses #2:
This implementation iterates over this
collection, checking each element
returned by the iterator in turn to
see if it's contained in the specified
collection. If it's not so contained,
it's removed from this collection with
the iterator's remove method
Although since this isn't in my reading of the original Collection interface's contract, I wouldn't necessarily assume the behavior of Collection to generally be this way.
Perhaps you should consider submitting suggested updates to the JavaDoc once you're done.
As to 'why the Collection interface was left so ambiguous' - I seriously doubt it was intentionally done - probably just something that wasn't given its due priority when that part of the API's were being written.