Why does an intermediate variable fix a typing issue with streams?

Viewed 79

I don't understand why the following program fails to compile:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class Main {
    public static void main(String[] args) {
        System.out.println(new ArrayList<Integer>(Arrays.asList(1, 2)).stream().map((Integer s) -> {
                return "" + (s * s);
        }).collect(Collectors.toCollection(ArrayList<String>::new)));
    }
}

whereas the following one compiles cleanly, the only difference being that I extracted the argument of println into a variable (whose type is even left to infer to the compiler).

import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class Main {
    public static void main(String[] args) {
        var r = new ArrayList<Integer>(Arrays.asList(1, 2)).stream().map((Integer s) -> {
                return "" + (s * s);
        }).collect(Collectors.toCollection(ArrayList<String>::new));
        System.out.println(r);
    }
}

For the first one, javac (16.0.1) reports:

$ javac -Xdiags:verbose  Main.java
Main.java:8: error: method println in class PrintStream cannot be applied to given types;
        System.out.println(new ArrayList<Integer>(Arrays.asList(1, 2)).stream().map((Integer s) -> {
                          ^
  required: String
  found:    ArrayList<String>
  reason: argument mismatch; inference variable R has incompatible bounds
      lower bounds: String,Collection<T#2>,Object
      lower bounds: ArrayList<String>
  where R,A,T#1,T#2,C are type-variables:
    R extends Object declared in method <R,A>collect(Collector<? super T#1,A,R>)
    A extends Object declared in method <R,A>collect(Collector<? super T#1,A,R>)
    T#1 extends Object declared in interface Stream
    T#2 extends Object declared in method <T#2,C>toCollection(Supplier<C>)
    C extends Collection<T#2> declared in method <T#2,C>toCollection(Supplier<C>)
1 error

Since I'm not a Java programmer, I can't tell if I'm facing a compiler bug, or a true limitation of the Java typing system that I don't understand. In the latter case, please point me to the appropriate documentation.

Thanks in advance.

0 Answers
Related