Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design decision of boolean containsAll(Collection<?> c) vs boolean addAll(Collection<? extends E> c); in collection framework [duplicate]

Why boolean containsAll(Collection < ?> c); method of collection framework is allowed for every type ?.But boolean addAll(Collection< ?extends E> c); allow for ? extends E.So,i wrote a program for clarification. Here is my program

public class ContainAllTest {
    // take ServiceDto 
    ArrayList<ServiceDto> resultList = new ArrayList<ServiceDto>();

    void Test() {

        ServiceDto serviceDto = new ServiceDto();
        serviceDto.setName("test");
        resultList.add(serviceDto);
        // another arraylist that takes String 
        ArrayList<String> resultList1 = new ArrayList<String>();
        resultList1.add("test");
        // no error, goes for run time.Contain all checking is done for two generic type ServiceDto and String:
        resultList.containsAll(resultList1);
        // error shown at compile time,as addAll take ServiceDto as generic type but the generic type for resultList1 take String:
        resultList.addAll(resultList1);    
    }

So,my question is when can i get advantage of resultList.containsAll(resultList1); when the generic type is different.In my case String and ServiceDto.Was there some thing wrong replacing boolean containsAll(Collection< ? > c) with boolean containsAll(Collection< ?extends E> c)

like image 991
abishkar bhattarai Avatar asked Aug 15 '13 07:08

abishkar bhattarai


2 Answers

I'm guessing the reason is that containsAll (and contains, remove, removeAll) uses Object#equals for the comparison.

You could, conceivably, have an overriden Object#equals method in E that can return true for objects of some unrelated class. Not that it would be a good idea, but it could be a valid implementation.

like image 134
Tobias Brandt Avatar answered Oct 05 '22 07:10

Tobias Brandt


This isn't to give an advantage it's to save cpu ticks. Generics are erased by the compiler and replaced with casts.

For the addAll method type safety needs to be taken into account. The user should only be allowed to add a Collection<E> or some subclass of E to a Collection<E>.

If you look at the source code for AbstractCollection you see this method:

public boolean addAll(Collection<? extends E> c) {
    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}

When compiled it will look (something) like

public boolean addAll(Collection c) {
    boolean modified = false;
    for (Object e : c)
        if (add((E)e))
            modified = true;
    return modified;
}

I.e. each and every element of the collection to be added needs to be cast from Object to E before being added.

For the containsAll method it doesn't matter. As the equals method is defined as equals(Object other) you can safely call it with any other Collection and there is no risk of ClassCastExceptions. By avoiding the use of generics the compiler can avoid adding in casts.

like image 23
Boris the Spider Avatar answered Oct 05 '22 07:10

Boris the Spider