javagenericscollections

Java <? extends Collection>


I have the following Java code:

List<? extends Collection<String>> attributes = new ArrayList<HashSet<String>>(nrAttributes);

...

attributes.replaceAll((in) -> {
        List<String> out = new ArrayList<>(); 
        out.addAll(in); 
        return out;
    });

But it gives me a compiler exception (last out is red) saying:

Type mismatch: cannot convert from List to capture#2-of ? extends Collection


Solution

  • Command line says:

    J:\WS\Java test>javac Main.java -Xdiags:verbose
    Main.java:11: error: method replaceAll in interface List<E> cannot be applied to given types;
            attributes.replaceAll((in) -> {
                                 ^
      required: UnaryOperator<CAP#1>
      found: (in)->{ Li[...]ut; }
      reason: argument mismatch; bad return type in lambda expression
          List<String> cannot be converted to CAP#1
      where E is a type-variable:
        E extends Object declared in interface List
      where CAP#1 is a fresh type-variable:
        CAP#1 extends Collection<String> from capture of ? extends Collection<String>
    1 error
    

    i.e. the ? capture, might be a sub-type or sibling of List<String>, so it is unsafe to add a List<String> to a List<? extends Collection>. The ...extends Collection doesn't really matter here.


    Possible solution:

    List<? extends Collection<String>> attributes = new ArrayList<HashSet<String>>(nrAttributes);
    
    ...
    
    List<List<String>> attribs2 = new ArrayList<>();
    
    attributes.forEach((in) -> {
        List<String> out = new ArrayList<>();
        out.addAll(in);
        attribs2.add(out);
    });
    

    Or:

    List<Collection<String>> attributes = new ArrayList<>(nrAttributes);        
    
    ...
    
    attributes.replaceAll((in) -> {
        List<String> out = new ArrayList<>();
        out.addAll(in);
        return out;
    });